BlueDog BlueDog - 5 months ago 77
Python Question

kivy python clock schedule update

'main_loop' function while loop does not increment self.i value every 5 seconds and 'run' function does not decrement self.mycounter value every 1 second.

Why?

What am I doing wrong?

I do not want to use time.sleep.

class MyThread(BoxLayout):
stop = []
timer = []
times = []

i = NumericProperty(0)
mycounter = NumericProperty(0)

def incrementi(self, *args):
self.i += 1

def decrementcounter(self,*args):
self.mycounter -= 1

def run(self):
self.mycounter = 30
while not self.stop:
self.timer.append(self.mycounter)
Clock.schedule_interval(self.decrementcounter, 1.0)
self.times.append(self.mycounter)
return self.mycounter

def main_loop(self):
self.i = 0
while True:
Clock.schedule_interval(self.incrementi, 5.0)
if self.i == 2:
self.mycounter = 30
threading.Thread(target = self.run).start()
if self.i == 5:
self.stop.append('dummystring')
if self.i == 6:
self.stop.pop(0)
self.timer = []
self.ids.lbl.text = "{}".format(self.i)
if self.i == 7:
self.i = 0

def read_it(self):
threading.Thread(target = self.main_loop).start()

class MyApp(App):
def build(self):
self.load_kv('thread.kv')
return MyThread()

if __name__ == "__main__":
app = MyApp()
app.run()


kivy.pv

<MyThread>:
Button:
text: "start program"
on_release: root.read_it()
Label:
id: lbl
text: "current step"
font_size: 50

Answer

I suggest you to throw away whole while styling if it's not necessary - especially that one in main_loop, which is just checking values. It's not good in kivy if you really don't need that functionality e.g.:

while <some list>:
    value = <some list>.pop()
    # do something

and even here are ways how to do it differently. As inclement suggested, using Clock is the right way. Also a little wrong detail in that particular loop is this:

while True:
    Clock.schedule_interval(self.incrementi, 5.0)

This will schedule interval infinitely many times, which will basically either freeze your app when you run this function or (if run in Thread) cause an endless loop/freeze + create a big memory eater = it will forbid you to Thread.set() i.e. stopping the thread and exiting the app correctly and in the end will crash.

I hope it's typo, because you only need to put it above while loop. Another thing: decrementcounter... It's in a while loop, it'll again create multiple Clocks and cause troubles. The same thing - again, put it either above the loop to make it work.

Basically while with time.sleep(t) is Clock.schedule_interval(some_function, t). It's nice that you want to check for something, but with each Clock.schedule_* you create another clock and I don't see anything that stops it. So basically you'll create infinitely many clocks.

Something more similar to while only(without sleep) is Clock.schedule_interval(some_function) i.e. you leave out time parameter and it'll call the function on each frame which if 60fps, then 60times per second. Quite precise for a simple value checking.