Search code examples
pythonmultithreadinguser-interfacekivysleep

Equivalent to `wx.CallLater()` in Kivy/KivyMD or how do deal with `time.sleep()` freezing the GUI?


I'm trying to make an app with KivyMD/Kivy, and I'd like to change a label's text multiple times with a few seconds of interval between the changes. I initially tried to do this with time.sleep(), but this froze up the GUI completely, which made the label changes and such not work.

I've seen that wxPython has the wx.CallLater() function which (if I understand correctly) will call a certain function in some amount of time without freezing up the GUI. In this thread, people were talking about threading, but it seemed to rise another problem without fixing the initial problem, so I'm really not sure if this would work in my case.

So is threading the way to go, is there an equivalent of wx.CallLater() in Kivy, or is there another better solution to my problem?

Working test code:

from kivymd.app import MDApp
from kivy.lang import Builder
import time

KV = '''
MDScreen:

    MDFillRoundFlatIconButton:
        id: button
        icon: 'git'
        on_release: app.some_func()
'''


class Test(MDApp):
    def build(self):
        return Builder.load_string(KV)

    def some_func(self):
        for i in range(3):
            self.root.ids.button.text = str(3 - i)
            time.sleep(3)

        self.root.ids.button.text = 'Go'


Test().run()

Solution

  • As @John Anderson suggested, the Clock object from kivy.clock has methods that achieve the same thing as wx.CallLater().

    from kivy.clock import Clock
    
    # to schedule an event once:
    Clock.schedule_once(lambda _: some_function(), in_x_seconds)
    
    # to schedule an event repeatedly:
    Clock.schedule_interval(lambda _: some_function(), every_x_seconds)