updating the label text using while true

442 views
Skip to first unread message

husam alkdary

unread,
Jun 3, 2020, 3:08:47 AM6/3/20
to Kivy users support
 I want to make a simple countdown timer I create a function to make this for me the function work when I use print but when I want to put the text on the label the app shows me is not responding  

the label class

class Timer_Label(Label):

 
def start_timer(self,sec,mi,hr):
 
print(type(sec))
 
while True:
 
print(type(sec),'1')
 time
.sleep(1)
 sec
-= 1
 
if sec == 00:
 sec
= 59
 mi
-= 1
 
if mi == 0:
 mi
= 59
 hr
-= 1
 
print(str(str(hr) + ':' + str(abs(mi)) + ':' + str(sec)))
 
self.text = str(str(hr) + ':' + str(mi) + ':' + str(sec))

I want to display the printed text on the self label 

Elliot Garbus

unread,
Jun 3, 2020, 10:44:44 AM6/3/20
to kivy-...@googlegroups.com

You don’t want to use endless loops or sleep statements.  You will never leave the while loop, and therefore not enter the kivy event loop… and as you found out, the code will be non responsive.

 

Instead you want to use Clock: https://kivy.org/doc/stable/api-kivy.clock.html?highlight=clock#module-kivy.clock

Use Clock to schedule a callback function to update the time.

 

In the example below I used timedelta from datetime to manage the clock math. 

https://docs.python.org/3/library/datetime.html#timedelta-objects

 

I used the python built-in locals() to get a dictionary of the arguments passed in, so I could loop over them to do the conversion from string to int.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.label import Label
from kivy.properties import StringProperty

from datetime import timedelta

kv =
"""
<CountDownTimerLabel>:
    text: root.countdown


BoxLayout:
    orientation: 'vertical'
    BoxLayout:
        size_hint_y: None
        height: 48
        TextInput:
            id: hours
            hint_text: 'Hours'
            input_filter: 'int'
        TextInput:
            id: minutes
            hint_text: 'Minutes'
            input_filter: 'int'
        TextInput
            id: seconds
            hint_text: 'Seconds'
            input_filter: 'int'
        Button:
            text: 'start'
            on_release: cdt.start(seconds.text, minutes.text, hours.text)
    CountDownTimerLabel:
        id: cdt
        font_size: 50
"""


class CountDownTimerLabel(Label):
    countdown = StringProperty(
'0:00:00')

   
def __init__(self, **kwargs):
       
self.schedule = None
       
self.timer = timedelta()
       
super().__init__(**kwargs)

   
def start(self, sec, mi, hr):  # String passed in
       
args = locals().copy()     # get the args passed in
       
del args['self']           # remove self, leaving sec, mi, hr
       
for key in args:           # convert strings to ints
           
args[key] = 0 if args[key] == '' else int(args[key])
       
self.timer = timedelta(hours=args['hr'], minutes=args['mi'], seconds=args['sec'])
       
self.countdown = str(self.timer)
       
if self.timer != timedelta():
           
self.schedule = Clock.schedule_interval(self._update, 1)

   
def _update(self, dt):
        
self.timer -= timedelta(seconds=1)
       
self.countdown = str(self.timer)
       
if self.timer == timedelta():  # if timer == 0 the cancel the schedule
           
self.schedule.cancel()


class CountDownTimerApp(App):
   
def build(self):
       
return Builder.load_string(kv)

CountDownTimerApp().run()

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/23bc2532-c057-4d1e-bbb5-646d1cc24310%40googlegroups.com.

 

husam alkdary

unread,
Jun 3, 2020, 1:36:48 PM6/3/20
to Kivy users support

but if I want to use clock function how I can pass the argument from the kv file to the countdown function ?

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-...@googlegroups.com.

Elliot Garbus

unread,
Jun 3, 2020, 3:01:53 PM6/3/20
to kivy-...@googlegroups.com
Look start button in the kv code.  It is calling start, and passing in the time. 

We are using the clock to create a callback once a second to update the text. 

Sent from my iPhone

On Jun 3, 2020, at 11:32 AM, husam alkdary <husamal...@gmail.com> wrote:


To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/e429519f-e2e9-42e4-845c-1207bd08a5fd%40googlegroups.com.

husam alkdary

unread,
Jun 4, 2020, 5:28:04 PM6/4/20
to Kivy users support
hi I used clock function in my code to make the countdown timer but I get some delay when I'm trying to close the popup after the entering of the counter initial time it's about 3 second what's the reasons of that and how I can fix it

my python code 


from kivy.app import App

from kivy.lang import Builder

from kivy.uix.label import Label

from time import strftime

from functools import partial


import time
from kivy.clock import Clock

from kivy.uix.popup import Popup

sec
= 0
mi
= 0
hr
= 0


class Clock_Date_Label(Label):
 
def show_time_date(self, *args):
 
self.text = str(strftime("Date: %d/%b/%Y\nTime: %H:%M:%S"))


class Timer_label(Label):
 
def show_timer(self, *args):
 
global sec
 
global mi
 
global hr
 ii
= 1
 
if App.get_running_app().root.ids.ko.text == "Pause":
 ii
-= 1
 sec
+= 1
 
if sec == 59:
 sec
= 0
 mi
+= 1
 
if mi == 60:
 mi
= 0
 hr
+= 1

 
self.text = str(str(hr) + ':' + str(mi) + ':' + str(sec))


 
def reset(self):
 
global mi
 
global hr
 
global sec
 sec
= 0
 hr
= 0
 mi
= 0
 
self.text = '0:0:0'

class Timer_Label(Label):

 
def start_timer(self,sec,mi,hr,*args):
 
print(hr, mi, sec)
 
if sec !=0:

 sec
-= 1

 
if sec == 00:
 sec
= 59
 mi
-= 1
 
if mi == 0:
 mi
= 59
 hr
-= 1

 
#print(str(str(hr) + ':' + str(abs(mi)) + ':' + str(sec)))

 
self.text = str(str(hr) + ':' + str(mi) + ':' + str(sec))

 
Clock.schedule_once(partial(self.start_timer, sec, mi, hr))#, 0)
time.sleep(1)



 

class Set_Timer(Popup):
 
pass

class KivyApp(App):

 
def build(self):
 
 
return Builder.load_file("main.kv")

 
def on_start(self):
 
Clock.schedule_interval(self.root.ids.Timer_label_id.show_timer, .5)
 
Clock.schedule_interval(self.root.ids.Clock_Date_Label_id.show_time_date, .5)

 
def open_set_timer_popup(self):
 
Set_Timer().open()

KivyApp().run()


and my main.kv file 

BoxLayout:
 orientation
: 'vertical'

 
Clock_Date_Label:
 size_hint_y
:.15
 id
: Clock_Date_Label_id
 color
:0,0,1,1
 font_size
: .1*self.width
 
TabbedPanel:
 do_default_tab
: False
 
TabbedPanelItem:
 background_color
:1,1,0,1
 text
: 'StopWatch'
 
BoxLayout:
 orientation
: 'vertical'
 canvas
.before:
 
Color:
 rgba
: 1,1,0,1
 
Rectangle:
 pos
: self.pos
 size
: self.size
 
Timer_label:
 id
: Timer_label_id
 font_size
: .1*self.width
 canvas
.before:
 
Color:
 rgba
: 1,1,0,1
 
Rectangle:
 pos
: self.pos
 size
: self.size
 
BoxLayout:
 
ToggleButton:
 id
: ko
 markup
: True
 text
: "start"
 on_press
: self.text ="start" if(ko.state == "normal") else("Pause")
 
Button:
 id
:ok
 text
: "reset"
 on_press
: app.root.ids.Timer_label_id.reset()
 
TabbedPanelItem:
 background_color
:0.5,0,1,1
 text
: 'Timer'
 
BoxLayout:
 orientation
: 'vertical'
 canvas
.before:
 
Color:
 rgba
: 0.5,0,1,1
 
Rectangle:
 pos
: self.pos
 size
: self.size
 
Timer_Label:
 size_hint_y
: 2
 id
: Timer_Label_id
 
ToggleButton:
 text
: 'Start' if self.state == 'normal' else 'Pause'
 id
: timer_ToggleButton_id

 
Button:
 text
: 'Reset'

 
Button:
 text
: 'Set Timer'
 on_press
: app.open_set_timer_popup()

<Set_Timer>:
 title
: 'Set the Timer'
 size_hint
:.7,.3
 pos_hint
:{ 'x':0,'y':0}
 id
: Set_Timer_popup
 
BoxLayout:
 orientation
: 'vertical'
 
BoxLayout
 
TextInput:
 hint_text
: 'hr'
 font_size
:.50* self.width
 id
: hr_id
 
TextInput:
 hint_text
: 'min'
 font_size
:.50* self.width
 id
: min_id
 
TextInput:
 hint_text
: 'sec'
 font_size
:.50* self.width
 id
: sec_id
 
BoxLayout:
 
Button:
 text
: 'Set'
 on_press
: app.root.ids.Timer_Label_id.start_timer(int(sec_id.text),int(min_id.text),int(hr_id.text))

 
#on_release: app.root.ids.Timer_Label_id.timer_start()
 
#on_press:print(type(int(sec_id.text)))
 on_press
: Set_Timer_popup.dismiss()
 
Button:
 text
: 'Clear'
 on_press
: hr_id.text = ''
 on_press
: min_id.text = ''
on_press
: sec_id.text = ''

thanks in advance 

Robert Flatt

unread,
Jun 4, 2020, 7:09:47 PM6/4/20
to Kivy users support
time.sleep(1)

NEVER use sleep() in a Kivy app (unless you know what Threads are)
Because sleep() causes a Kivy app to be unresponsive, which is what you see.
Or put another way, don't ignore Elliot's excellent advice.  ;)

Yes, this means the idea of a countdown timer base on sleep() is deeply flawed.

If you want a timer, figure out the time you want it to be triggered and test for trigger >= current time, and not "Pause"
On pause/normal button events note the difference between "Pause" time and "normal" time and adjust the trigger time accordingly.

You are experienced enough to code this.
Avoid disapointment, don't ask me to code this for you.

Elliot Garbus

unread,
Jun 4, 2020, 7:41:35 PM6/4/20
to kivy-...@googlegroups.com

Looks like your code indents did not survive the paste and email.  Here are a few things I see.

  1. Never use time.sleep(), kivy runs an event loop.  If you call sleep() it will cause the program to lock-up for the sleep time.
  2. This is a problem:
    1. Clock.schedule_once(partial(self.start_timer, sec, mi, hr))

You are calling start_timer every frame, about 15ms.  There is no need for this level of resolution. 

                      You could use: Clock.schedule_once(partial(self.start_timer, sec, mi, hr), 1)  # this will be called once a second.

 

 

Other items.  You do not need any global vars here.  You could use then as class members, but even then, not necessary and error prone.

Look at the example I gave you.  Read how to use the datetime module. 

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/76cb3097-a820-483d-9522-0b73ff6b837eo%40googlegroups.com.

 

husam alkdary

unread,
Jun 5, 2020, 3:44:28 AM6/5/20
to Kivy users support
thank you my friend Elliot Garbus your notes solved my issue I just delete time.sleep(1) and then replaced the Clock.schedule_once(partial(self.start_timer, sec, mi, hr)) with Clock.schedule_once(partial(self.start_timer, sec, mi, hr), 1) 

husam alkdary

unread,
Jun 5, 2020, 2:01:05 PM6/5/20
to Kivy users support
hello again I have some issue in the above code I have a rule widget <Set_Timer> popup but how I can refer to the ids in the rule widget 'popup' inside the root widget ?
I tried the app.root.ids but is not work

Elliot Garbus

unread,
Jun 5, 2020, 2:54:08 PM6/5/20
to kivy-...@googlegroups.com

You could take a different approach.  It looks like you are setting or clearing the text values for hr, min and sec in the popup.

 

In app create string properties for hr, min, sec and use those values in the popup.

class KivyApp(App):
    hr = StringProperty()

    min = StringProperty()

    sec = StringPropert()

 

then in kv, in your popup.

 

TextInput:

    text: app.hr

    on_text: app.hr = self.text

 

Button:

    text: ‘clear’

    on_release: app,hr = app.min = app.sec = ''

 

 

Or to access the popup:  in the App instance the Popup, and use it to reference the ids.  Something like:

class KivyApp(App):

    def __init__(self, **kwargs):

        timer_popup = Set_Timer()    # Create the instance of the popup

        super().__init__(**kwargs)



   
def build(self):
        
return Builder.load_file("main.kv")

 
def on_start(self):
    
Clock.schedule_interval(self.root.ids.Timer_label_id.show_timer, .5)
    
Clock.schedule_interval(self.root.ids.Clock_Date_Label_id.show_time_date, .5)

 
def open_set_timer_popup(self):


    
self.timer_popup.open()  # open the popup like this

     print(self.timer_popup.ids)  # access the ids

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/15780daf-9d24-4856-91e0-eed3c3328ea2o%40googlegroups.com.

 

husam alkdary

unread,
Jun 6, 2020, 3:54:44 AM6/6/20
to Kivy users support
I used some of you note to make restart button in timer screen

main.py

from kivy.app import App

from kivy.lang import Builder

from kivy.uix.label import Label

from time import strftime

from functools import partial


import time
from kivy.clock import Clock

from kivy.uix.popup import Popup

sec
= 0
mi
= 0
hr
= 0


class Clock_Date_Label(Label):
 
def show_time_date(self, *args):


 
if int(strftime("%H")) >= 12:
 
self.text = str(strftime("Date: %d/%b/%Y\nTime: %H:%M:%S pm"))
 
else:
 
self.text = str(strftime("Date: %d/%b/%Y\nTime: %H:%M:%S am"))



class Timer_label(Label):
 
def show_timer(self, *args):


 
global mi
 
global hr
 
global sec
 ii
= 1
 
if App.get_running_app().root.ids.StopWatch_ToggleButton_id.text == "Pause":

 ii
-= 1
 sec
+= 1
 
if sec == 59:
 sec
= 0
 mi
+= 1
 
if mi == 60:
 mi
= 0
 hr
+= 1
 
self.text = str(str(hr) + ':' + str(mi) + ':' + str(sec))

 
def reset(self):
 
global mi
 
global hr
 
global sec
 sec
= 0
 hr
= 0
 mi
= 0

 
self.text = '00:00:00'





class Timer_Label(Label):

 
def start_timer(self,sec,mi,hr,*args):
 
if App.get_running_app().root.ids.timer_ToggleButton_id.text == "Pause":

 
if sec !=0:
 sec
-= 1
 
if sec == 00:
 sec
= 59
 mi
-= 1
 
if mi == 0:
 mi
= 59
 hr
-= 1

 
self.text = str(str(hr) + ':' + str(mi) + ':' + str(sec))

 
Clock.schedule_once(partial(self.start_timer, sec, mi, hr), 1)

 
def restart_timer(self,sec,mi,hr,*args):
 
Clock.schedule_once(partial(self.start_timer, sec, mi, hr))
 
print(sec,mi,hr)


 

class Set_Timer(Popup):
 
pass




class KivyApp(App):

 
def build(self):

 
return Builder.load_file("main.kv")

 
def on_start(self):
 
Clock.schedule_interval(self.root.ids.Timer_label_id.show_timer, .5)
 
Clock.schedule_interval(self.root.ids.Clock_Date_Label_id.show_time_date, .5)

 
def open_set_timer_popup(self):
 
Set_Timer().open()


KivyApp().run()

 

kv file

BoxLayout:
 timer_Seconds_reset
: ''
 timer_Minutes_reset
: ''
 timer_Hours_reset
:''
 orientation
: 'vertical'
 
TabbedPanel:
 do_default_tab
: False
 
TabbedPanelItem:
 background_color
: .3,.8,.1,1
 text
: 'Clock'
 
BoxLayout:
 canvas
.before:
 
Color:
 rgba
: .3,.8,.1,1

 
Rectangle:
 pos
: self.pos
 size
: self.
size
 
Clock_Date_Label:

 id
: Clock_Date_Label_id
 color
:0,0,1,1
 font_size
: .1*self.
width


 
TabbedPanelItem:

 background_color
:1,1,0,1
 text
: 'StopWatch'
 
BoxLayout:
 orientation
: 'vertical'
 canvas
.before:
 
Color:
 rgba
: 1,1,0,1
 
Rectangle:
 pos
: self.pos
 size
: self.size
 
Timer_label:
 id
: Timer_label_id
 font_size
: .1*self.width
 canvas
.before:
 
Color:
 rgba
: 1,1,0,1
 
Rectangle:
 pos
: self.pos
 size
: self.size
 
BoxLayout:
 
ToggleButton:

 id
: StopWatch_ToggleButton_id
 text
: "Start"
 on_press
: self.text ="start" if(StopWatch_ToggleButton_id.state == "normal") else("Pause")
 
Button:
 id
:ok
 text
: "Reset"

 on_press
: app.root.ids.Timer_label_id.reset()
 
TabbedPanelItem:
 background_color
:0.5,0,1,1
 text
: 'Timer'
 
BoxLayout:
 orientation
: 'vertical'
 canvas
.before:
 
Color:
 rgba
: 0.5,0,1,1
 
Rectangle:
 pos
: self.pos
 size
: self.size
 
Timer_Label:
 size_hint_y
: 2
 id
: Timer_Label_id
 
ToggleButton:

 text
: 'Pause' if self.state == 'normal' else 'Start'
 id
: timer_ToggleButton_id

 
Button:
 text
: 'Restart'
 on_press
: app.root.ids.Timer_Label_id.restart_timer(int(root.timer_Seconds_reset),int(root.timer_Minutes_reset),int(root.timer_Hours_reset))


 
Button:
 text
: 'Set Timer'
 on_press
: app.open_set_timer_popup()


<Set_Timer>:
 title
: 'Set the Timer'
 size_hint
:.7,.3

 id
: Set_Timer_popup
 
BoxLayout:
 orientation
: 'vertical'
 
BoxLayout:
 
TextInput:
 hint_text
: 'hr'
 font_size
:.50* self.
width
 text
: app.root.timer_Hours_reset
 id
: hr_id
 focuse
: True if len(self.text) <= 2 else False

 
TextInput:
 hint_text
: 'min'
 font_size
:.50* self.
width
 text
: app.root.timer_Minutes_reset
 id
: min_id
 
TextInput:

 hint_text
: 'sec'
 font_size
:.50* self.
width
 text
: app.root.timer_Seconds_reset
 id
: sec_id
 
BoxLayout:

 
Button:
 text
: 'Set'
 on_press
: app.root.ids.Timer_Label_id.start_timer(int(sec_id.text),int(min_id.text),int(hr_id.text))

 on_press
: app.root.timer_Seconds_reset =sec_id.text
 on_press
: app.root.timer_Minutes_reset =min_id.text
 on_press
: app.root.timer_Hours_reset = hr_id.text
 
#on_release: app.root.ids.Timer_Label_id.timer_start()

 
#on_press:print(type(int(sec_id.text)))
 on_press
: Set_Timer_popup.dismiss()
 
Button:
 text
: 'Clear'
 on_press
: hr_id.text = ''
 on_press
: min_id.text = ''
 on_press
: sec_id.text = ''


when I click the restart button in the timer screen it first work well and then it's shows random numbers even if the input is not  0:0:0
I want this button to restart the timer from the beginner using the same user input

Elliot Garbus

unread,
Jun 6, 2020, 11:52:35 AM6/6/20
to kivy-...@googlegroups.com

Please send code that is properly indented or attach a file.  Something is causing your code the ‘flatten’.

You are creating object properties in kv, (app.root.timer_Seocnds_reset), I’d recommend creating these properties in Python, you get the benefit of error checking.

 

Here are a few things I can see that look problematic:

You are repeating on_press, you should have 1 on_press, you can have multiple actions associated with it.

 

Instead of:

Button:
    text
: 'Set'
        on_press
: app.root.ids.Timer_Label_id.start_timer(int(sec_id.text),int(min_id.text),int(hr_id.text))
        on_press
: app.root.timer_Seconds_reset =sec_id.text
        on_press
: app.root.timer_Minutes_reset =min_id.text
        on_press
: app.root.timer_Hours_reset = hr_id.text

Use:

Button:
    text
: 'Set'
        on_press
:

            app.root.ids.Timer_Label_id.start_timer(int(sec_id.text),int(min_id.text),int(hr_id.text))
            app
.root.timer_Seconds_reset =sec_id.text
            app
.root.timer_Minutes_reset =min_id.text
            app
.root.timer_Hours_reset = hr_id.text

Your Clear button is not clearing your properties.  It is only clearing the text field.

 

 

FWIW:  This test is not required, look up %p in the strftime documentation.

if int(strftime("%H")) >= 12:
   
self.text = str(strftime("Date: %d/%b/%Y\nTime: %H:%M:%S pm"))
 
else:
   
self.text = str(strftime("Date: %d/%b/%Y\nTime: %H:%M:%S am"))

 

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/acd7d286-696d-4782-ae92-08235090cf60o%40googlegroups.com.

 

husam alkdary

unread,
Jun 6, 2020, 1:54:16 PM6/6/20
to Kivy users support
hi I attached the complete code to test my issue which is when I set the countdown time to be 1:1:1 for example and then press the restart button the algorithm that I write will launch the restart_timer  function that will take the app.root string property as argument then will pass it to the start_timer that will restart the timer as I hope but It's shows some random numbers on the Timer_Label not as expected that's my main issue 
kivy app.txt

Elliot Garbus

unread,
Jun 6, 2020, 2:11:25 PM6/6/20
to kivy-...@googlegroups.com

For your reference, I extended my example with a pause and reset button.

 

"""
        Button:
            text: 'reset'
            on_release: cdt.reset()
        ToggleButton:
            text: 'pause'
            on_release: cdt.pause()

    CountDownTimerLabel:
        id: cdt
        font_size: 50
"""


class CountDownTimerLabel(Label):
    countdown = StringProperty(
'0:00:00')

   
def __init__(self, **kwargs):
       
self.schedule = None
       
self
.timer = timedelta()
       
self.is_running = False
       
super().__init__(**kwargs)

    
def start(self, sec, mi, hr):  # String passed in
       
if self.schedule:
           
return
       
args = locals().copy()     # get the args passed in
       
del args['self']           # remove self, leaving sec, mi, hr
       
for key in args:           # convert strings to ints
           
args[key] = 0 if args[key] == '' else int(args[key])
       
self.timer = timedelta(hours=args['hr'], minutes=args['mi'], seconds=args['sec'])
       
self.countdown = str(self.timer)
       
if self.timer != timedelta():
           
self.schedule = Clock.schedule_interval(self._update, 1)
           
self.is_running = True

    def
_update(self, _):
       
self.timer -= timedelta(seconds=1)
       
self.countdown = str(self.timer)
       
if self.timer == timedelta():
           
self.schedule.cancel()
           
self.schedule = None
           
self.is_running = False

    def
reset(self):
       
self.countdown = str(timedelta())
       
if self.schedule:
           
self.schedule.cancel()
           
self.schedule = None
           
self.is_running = False

    def
pause(self):
       
if not self.is_running:
           
return
        if
self.schedule:
           
self.schedule.cancel()  # Pause
           
self.schedule = None
        else
:
           
self.schedule = Clock.schedule_interval(self._update, 1# Resume


To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/c3e5c299-b57b-465f-8013-8dc3fbd89cd3o%40googlegroups.com.

 

Elliot Garbus

unread,
Jun 6, 2020, 2:33:49 PM6/6/20
to kivy-...@googlegroups.com

When start_timer() is called,  you effectively have a loop that every second in updating the label. 

When you press restart you are adding a second timer loop that is updating the same label with a different initial value.

At this point you have two loops   Each time you press restart, you create an additional loop.  Print out the arguments when you enter start_timer to see this in more detail.

 

When you enter restart you will need to cancel the other timer that is running.  You can refer to the example I just send for an example of how to cancel the timer.

Also read: https://kivy.org/doc/stable/api-kivy.clock.html?highlight=clock#unscheduling

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/c3e5c299-b57b-465f-8013-8dc3fbd89cd3o%40googlegroups.com.

 

husam alkdary

unread,
Jun 8, 2020, 2:40:14 AM6/8/20
to Kivy users support
HI it's possible to unscheduled function using other function without using  def __init__(self, **kwargs): function because I want to unscheduled start_timer using  restart_timer

Elliot Garbus

unread,
Jun 8, 2020, 11:19:30 AM6/8/20
to kivy-...@googlegroups.com

You want to declare and initialize your instance variables in the __init__ this is a class member at the same level as your other methods.  In the class you access the class variable using the self pointer. 

 

Review instance attributes here: https://realpython.com/python3-object-oriented-programming/

 

You can also access these attributes from python below I instance the class, and then access the variable:

my_timer = Timer_Lable()

print(my_timer.schedule)

 

Applied to your code:

 

class Timer_Label(Label):
   
def __init__(self,**kwargs):
       
self.schedule = None
       
super().__init__(**kwargs)

   
def start_timer(self, sec, mi, hr, *args):
       
if App.get_running_app().root.ids.timer_ToggleButton_id.text == "Pause":
           
if sec != 0:
                sec -=
1
           
if sec == 00:
                sec =
59
               
mi -= 1
           
if mi == 0:
                mi =
59
                
hr -= 1
       
self.text = str(str(hr) + ':' + str(mi) + ':' + str(sec))
       
self.schedule = Clock.schedule_once(partial(self.start_timer, sec, mi, hr), 1)

   
def restart_timer(self, sec, mi, hr, *args):
       
self.schedule.cancel()
       
# Clock.schedule_once(partial(self.start_timer, 0, 0, 0))
       
self.schedule = Clock.schedule_once(partial(self.start_timer, sec, mi, hr), 1)
       
print(sec, mi, hr)

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/1d50a4d0-b861-4959-8ccb-6a4edb74939co%40googlegroups.com.

 

husam alkdary

unread,
Jun 9, 2020, 1:20:35 AM6/9/20
to Kivy users support
wow thanks my work as I wanted but I want to give me a short discerption about this two line
def __init__(self, **kwargs):
   
   
super().__init__(**kwargs)

I want to knew what the use of them and how they work in kivy

Elliot Garbus

unread,
Jun 9, 2020, 8:12:29 AM6/9/20
to kivy-...@googlegroups.com

Here is a description:

 

class TimerLabel(Label):
   
def __init__(self,**kwargs):
        self.schedule = None
        super().__init__(**kwargs)

 

The code above defined a class, TimerLabel.  When TimerLabel is created (instanced), the __init__ method runs.  Parameters passed when creating the object are passed to the __init__() method.  Kivy uses keyword arguments (kwargs) to construct objects.  For example, we can create a TimerLabel as follows:

 

t_label = TimerLabel(color=(1, 1, 1, 1),  text=’junk’, size_hint=(.5, .7))

 

The arguments for TimerLabel get passed to TimerLabel’s __init__() method.  In order to take a variable number of key word arguments, the ** is used.  Kwargs is used by convention, or together **kwargs.  The kwargs parameter is a dict that contains all of the passed keyword arguments.

 

TimerLabel is a child of Label.  (Or this can be described as the TimerLabel class inherits from Label or is derived from Label)  When we overload the __init__ method, we still need to call the parents (Label) __init__ method.  The python built-in super() https://docs.python.org/3/library/functions.html#super

Is used to call the parents __init__ method, and we pass the kwargs we received, so they can be used by the parent.

 

Hope that helps.

Reference:

**kwargs:  https://realpython.com/python-kwargs-and-args/  

__init__():  https://realpython.com/python3-object-oriented-programming/

super(): https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/639c61ec-b670-4a80-b82e-adaad9fdabc6o%40googlegroups.com.

 

husam alkdary

unread,
Jun 10, 2020, 3:31:59 PM6/10/20
to Kivy users support
hi I tried your method to access the popup ids 
class KivyApp(App):



   
def __init__(self, **kwargs):

        timer_popup
= Set_Timer()    # Create the instance of the popup

       
super().__init__(**kwargs)


   
def build(self):
         
return Builder.load_file("main.kv")

 
def on_start(self):
     
Clock.schedule_interval(self.root.ids.Timer_label_id.show_timer, .5)
     
Clock.schedule_interval(self.root.ids.Clock_Date_Label_id.show_time_date, .5)

 
def open_set_timer_popup(self):
     
self.timer_popup.open()  # open the popup like this



     
print(self.timer_popup.ids)  # access the ids

but the popup specifications is as the default popup specifications the specifications  not that I wrote in the kv file 




husam alkdary

unread,
Jun 10, 2020, 4:01:53 PM6/10/20
to Kivy users support
how to use the popup specification that I wrote in the kv file 

Elliot Garbus

unread,
Jun 10, 2020, 4:08:20 PM6/10/20
to kivy-...@googlegroups.com

Move the creation of the popup to on_start.

The kv has not been applied when the __init__() is executing.

 

Here is a complete example:

 

from kivy.app import App
from kivy.uix.popup import Popup
from kivy.lang import Builder

kv =
"""
<EmergencyPopup>
    size_hint: .7, .7
    title: 'Emergency'
    BoxLayout:
        orientation: 'vertical'
        Label:
            id: pop_label
            text: 'Your hair is on fire!'
            font_size: 20
        Button:
            id: pop_button
            size_hint_y: None
            height: 48
            text: 'OK'
            on_release: root.dismiss()
           
BoxLayout:
    Button:
        text: 'Press for Popup'
        on_release: app.open_popup()
"""


class EmergencyPopup(Popup):
   
pass


class
TestPopApp(App):
   
def __init__(self, **kwargs):
       
self.e_pop = None
       
super().__init__(**kwargs)

   
def build(self):
       
return Builder.load_string(kv)

   
def open_popup(self):
       
self.e_pop.open()

   
def on_start(self):
       
self.e_pop = EmergencyPopup()
       
print(self.e_pop.ids)

TestPopApp().run()

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/0861c9cb-e26f-455d-b87e-50afe82264c0o%40googlegroups.com.

 

husam alkdary

unread,
Jun 11, 2020, 2:49:19 AM6/11/20
to Kivy users support
thank you a lot Elliot it was a great and helpful conversation

Elliot Garbus

unread,
Jun 11, 2020, 11:10:10 AM6/11/20
to kivy-...@googlegroups.com

😊

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/6b8317b4-e943-4f76-80fe-ba37038b4dbeo%40googlegroups.com.

 

Reply all
Reply to author
Forward
0 new messages