How to schedule a schedule with kivy

Asked

Viewed 99 times

0

I want to make an event happen for 2 seconds at the speed of 29/30, after 5 seconds passed since the beginning of the program, with the following code:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.clock import *

class LoginScreen(GridLayout):
    def __init__(self, **kwargs):
        super(LoginScreen, self).__init__(**kwargs)
        self.cols = 2
        self.add_widget(Label(text='User Name'))
        self.username = TextInput(multiline=False)
        self.add_widget(self.username)
        self.add_widget(Label(text='password'))
        self.password = TextInput(password=True, multiline=False)
        self.add_widget(self.password)

stop= 0

class MyApp(App):

    def build(self):

        return LoginScreen()

    def my_callback(dt):
        global stop
        if stop == 1:
            print ('Last call of my callback, bye bye !')
            return False
        print ('My callback is called')

    def stop_my_callback(dt):
        global stop
        stop = 1

    def start_my_callback(dt):
        event = Clock.schedule_interval(my_callback, 29 / 30.)
        Clock.schedule_once(stop_my_callback, 2)

    Clock.schedule_once(start_my_callback, 5)

if __name__ == '__main__':
    MyApp().run()

However, after 5 seconds, the console returns:

 Traceback (most recent call last):
   File "C:\Users\enzo\Desktop\teste.py", line 44, in <module>
     MyApp().run()
   File "C:\Users\enzo\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\app.py", line 826, in run
     runTouchApp()
   File "C:\Users\enzo\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 502, in runTouchApp
     EventLoop.window.mainloop()
   File "C:\Users\enzo\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 727, in mainloop
     self._mainloop()
   File "C:\Users\enzo\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 460, in _mainloop
     EventLoop.idle()
   File "C:\Users\enzo\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 337, in idle
     Clock.tick()
   File "C:\Users\enzo\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\clock.py", line 581, in tick
     self._process_events()
   File "kivy\_clock.pyx", line 384, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 414, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 412, in kivy._clock.CyClockBase._process_events
   File "kivy\_clock.pyx", line 167, in kivy._clock.ClockEvent.tick
   File "C:\Users\enzo\Desktop\teste.py", line 38, in start_my_callback
     event = Clock.schedule_interval(my_callback, 29 / 30.)
 NameError: name 'my_callback' is not defined

How can I fix this?

1 answer

1


When defining class methods, the first parameter is always the class instance being used to call the method, and is passed automatically by python. By convention, the name self:

def my_callback(self, dt):
    ...
def stop_my_callback(self, dt):
    ...
def start_my_callback(self, dt):
    ...

One of the advantages of using classes is no longer having to use global ones, avoiding all the confusion they can cause. Instead, it becomes possible to store data according to the context, through attributes of the class or its instances. In the example below we can use an instance attribute through self.stop:

def start_my_callback(self, dt):
    self.stop = 0
    ...

def stop_my_callback(self, dt):
    self.stop = 1

def my_callback(self, dt):
    if self.stop == 1:
        ...

Another change is when referring to a method. After defining a class, the methods become attributes of the instances. Thus, if you are within a class method, you can use the self to obtain the reference to another method, in the example self.my_callback:

def start_my_callback(self, dt):
    self.event = Clock.schedule_interval(self.my_callback, 29 / 30.)
    Clock.schedule_once(self.stop_my_callback, 2)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.