I have made a simple timer program and a box layout with a label and a button in Kivy. Whenever the button is pressed, I want the timer to start and the label to display the time passed. I followed this tutorial: https://www.youtube.com/watch?v=cggCobcS3vU and then added some of my own stuff to the code, but the label only displays the initial text set in the .kv file. Any fix?
timer.py
import time
from kivy.app import App
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.properties import StringProperty, ObjectProperty
class MyApp(BoxLayout):
def __init__(self, **kwargs):
super(MyApp, self).__init__(**kwargs)
self.output = ''
def update_label(self):
self.lbl1.text = str(self.output)
def count(self, *varargs):
timeLoop = True
Sec = 0
Min = 0
Hrs = 0
while timeLoop == True:
self.update_label()
print(str(self.output))
Sec += 1
time.sleep(1)
if Sec == 60:
Sec = 0
Min += 1
if Min == 60:
Min = 0
Hrs += 1
if Sec <= 9 and Min <=9 and Hrs <= 9:
self.output = '0' + str(Hrs) +'.'+ '0' + str(Min) + "." + '0' + str(Sec)
elif Sec <= 9 and Min <=9 and Hrs >=9:
self.output = str(Hrs) + '.'+ '0' + str(Min) + "." + '0' + str(Sec)
elif Sec <= 9 and Min >=9 and Hrs >=9:
self.output = str(Hrs) + '.'+ str(Min) + "." + '0' + str(Sec)
elif Sec >= 9 and Min >=9 and Hrs >=9:
self.output = str(Hrs) + '.'+ str(Min) + "." + str(Sec)
elif Sec >= 9 and Min >=9 and Hrs <=9:
self.output = '0' + str(Hrs) +'.'+ str(Min) + "." + str(Sec)
elif Sec >= 9 and Min <= 9 and Hrs <=9:
self.output = '0' + str(Hrs) +'.'+ '0' + str(Min) + "." + str(Sec)
elif Sec >= 9 and Min <=9 and Hrs >= 9:
self.output = str(Hrs) +'.'+ '0' + str(Min) + "." + str(Sec)
elif Sec <= 9 and Min >= 9 and Hrs <=9:
self.output = '0' + str(Hrs) +'.'+ str(Min) + "." + '0' + str(Sec)
class MainApp(App):
def build(self):
c = MyApp()
return c
if __name__ == '__main__':
MainApp().run()
mainapp.kv
<MyApp>:
lbl1: label1
BoxLayout:
size: root.size
Button:
id: button1
text: "Change text"
on_press: root.count()
Label:
id: label1
text: "hi"
I am aware of this: How to change text of a label in the kivy language with python
and this: https://groups.google.com/forum/#!topic/kivy-users/mdqPQYBWEU8
But neither seems to work for me.
Blocking tasks such as time.sleep()
together with an infinite loop are not GUI friendly since it lives in an event loop, so blocking tasks will not allow handling other events such as changing the size of the window, moving the window, etc.
Kivy can create periodic tasks without using True or time.sleep()
, for this Clock
is used:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
class MyApp(BoxLayout):
def __init__(self, **kwargs):
super(MyApp, self).__init__(**kwargs)
self.output = ''
def update_label(self):
self.lbl1.text = str(self.output)
def count(self, *varargs):
self.Sec = 0
self.Min = 0
self.Hrs = 0
Clock.schedule_interval(self.on_timeout, 1)
def on_timeout(self, *args):
self.update_label()
self.Sec += 1
if self.Sec == 60:
self.Sec = 0
self.Min += 1
if self.Min == 60:
self.Min = 0
self.Hrs += 1
if self.Sec <= 9 and self.Min <=9 and self.Hrs <= 9:
self.output = '0' + str(self.Hrs) +'.'+ '0' + str(self.Min) + "." + '0' + str(self.Sec)
elif self.Sec <= 9 and self.Min <=9 and self.Hrs >=9:
self.output = str(self.Hrs) + '.'+ '0' + str(self.Min) + "." + '0' + str(self.Sec)
elif self.Sec <= 9 and self.Min >=9 and self.Hrs >=9:
self.output = str(self.Hrs) + '.'+ str(self.Min) + "." + '0' + str(self.Sec)
elif self.Sec >= 9 and self.Min >=9 and self.Hrs >=9:
self.output = str(self.Hrs) + '.'+ str(self.Min) + "." + str(self.Sec)
elif self.Sec >= 9 and self.Min >=9 and self.Hrs <=9:
self.output = '0' + str(self.Hrs) +'.'+ str(self.Min) + "." + str(self.Sec)
elif self.Sec >= 9 and self.Min <= 9 and self.Hrs <=9:
self.output = '0' + str(self.Hrs) +'.'+ '0' + str(self.Min) + "." + str(self.Sec)
elif self.Sec >= 9 and self.Min <=9 and self.Hrs >= 9:
self.output = str(self.Hrs) +'.'+ '0' + str(self.Min) + "." + str(self.Sec)
elif self.Sec <= 9 and self.Min >= 9 and self.Hrs <=9:
self.output = '0' + str(self.Hrs) +'.'+ str(self.Min) + "." + '0' + str(self.Sec)
class MainApp(App):
def build(self):
c = MyApp()
return c
if __name__ == '__main__':
MainApp().run()
Plus:
Instead of doing a tedious calculation to obtain the time we can reduce it using the libraries:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from datetime import datetime
class MyApp(BoxLayout):
def count(self, *varargs):
self.start = datetime.now()
Clock.schedule_interval(self.on_timeout, 1)
def on_timeout(self, *args):
d = datetime.now() - self.start
self.lbl1.text = datetime.utcfromtimestamp(d.total_seconds()).strftime("%H.%M.%S")
class MainApp(App):
def build(self):
c = MyApp()
return c
if __name__ == '__main__':
MainApp().run()