I have a countdown timer that starts at a random integer number within the range given by the randint() arguments and counts down to zero. The aim is to make the timer restart at a new random number the first time it reaches zero (i.e. lap function) and to display "FINISH" the second time it reaches zero.
This is my first time using kivy, so apologies if the solution is obvious. At present I only require two iterations, but I may need to adjust this later so that the timer will lap any number of times before finally stopping. The number of laps will be determined in the code before running the app, and not by the app user whilst running the app.
from kivy.app import App
from kivy.uix.label import Label
from kivy.animation import Animation
from kivy.properties import NumericProperty
from random import randint
class IncrediblyCrudeClock(Label):
for i in range(2):
r=randint(3,7)
a = NumericProperty(r) # Number of seconds to countdown
def start(self): #Function to initiate the countdown
Animation.cancel_all(self) # stop any current animations
self.anim = Animation(a=0, duration=self.a) #a=0 sets the
#final destination of a. duration sets the time taken to reach stopping
#point (i.e 5 seconds for a=5)
def finish_callback(animation, incr_crude_clock):
if self.i==1:
incr_crude_clock.text = "FINISHED" #when the clock
#reaches zero, display "FINISHED"
self.anim.bind(on_complete=finish_callback) #call the
#finish_callback function once a=0
self.anim.start(self) #Start the animation (otherwise clock
#stuck at 5 for a=5)
class TimeApp(App):
def build(self):
crudeclock = IncrediblyCrudeClock()
crudeclock.start()
return crudeclock
if __name__ == "__main__":
TimeApp().run()
<IncrediblyCrudeClock>
text: str(round(self.a, 1))
The app does run as expected for the first countdown. A random number is selected and the timer counts down to zero, but it stops and displays "FINISHED" after the first count down. It seems as though the for loop is iterating from zero to one before the app is actually started, so, by the time the countdown starts, i is already equal to 1 (in stead of running first from a to zero with i=0 and then from new a to zero with i=1). I imagine this is because the for loop is in the wrong place (i.e. not upon calling the start function), but I have been unable to work out how to rectify this. This is also my first time using stack overflow, so please let me know if you need to know anything else.
Here is a version that repeats the countdown a specified number of times:
from random import randint
from kivy.animation import Animation
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.label import Label
class IncrediblyCrudeClock(Label):
a = NumericProperty(0) # Number of seconds to countdown
def __init__(self, **kwargs):
self.max_laps = kwargs.pop('laps', 2) # default is to do 2 laps
self.lap_counter = 0
super(IncrediblyCrudeClock, self).__init__(**kwargs)
def start(self, *args):
self.lap_counter += 1
self.a = randint(3, 7)
self.anim = Animation(a=0, duration=self.a)
if self.lap_counter >= self.max_laps:
# this is the last lap, set on_complete to call self.finish_callback
self.anim.bind(on_complete=self.finish_callback)
else:
# not finished yet, call self.start again
self.anim.bind(on_complete=self.start)
print('starting anim number', self.lap_counter)
self.anim.start(self)
def finish_callback(self, animation, incr_crude_clock):
print('in finish_callback')
self.text = 'FINISHED'
Builder.load_string('''
<IncrediblyCrudeClock>
text: str(round(self.a, 1))
''')
class TimeApp(App):
def build(self):
# specify the number of repetitions in the constructor
crudeclock = IncrediblyCrudeClock(laps=3)
crudeclock.start()
return crudeclock
if __name__ == "__main__":
TimeApp().run()