Kotejichizu
Kotejichizu

Reputation: 35

Python kivy clock shedule interval updating

I have a problem with changing intervals of clock updates. I need to change the intervals while running the clock. I am still new to the kivy library and it's my first bigger project so I just have a basic understading how it all works.

My initial plan of just changing the value doesnt work. I can see the values changing, but the clock stays the same.

class MainWindow(Screen):

    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        Clock.schedule_interval(self.btn, player.clock_interval)

    def reduce_clock_interval(self):
        player.clock_interval -= 1

The reduce_clock_interval() function is called later with a button:

<SecondWindow>:
    name: "second"
    BoxLayout:     
        BoxLayout:
            BoxLayout:
                Button:    
                    text: "Reduce time"
                    on_press: root.reduce_clock_interval()

I have also tried using the Clock.cancel() to stop the current clock and create a new one with new values, but still can't get it to work.

class MainWindow(Screen):

    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        clock = Clock.schedule_interval(self.btn, player.clock_interval)

    def reduce_clock_interval(self):
        player.clock_interval -= 1
        Clock.cancel(MainWindow.__init__.clock)
        clock = Clock.schedule_interval(self.btn, player.clock_interval)

Update:

I have made some changes while tinkering with the code in meantime: -moved the clock_interval to the MainWindow class -moved reduce_clock_interval function to SecondWindow

Minimal reproducible example:

1 .py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock

class MainWindow(Screen):
    clock_interval = 5

    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        self.clock = Clock.schedule_interval(self.btn, self.clock_interval)

    def btn(self, *args):
        print(*args)
        print(MainWindow.clock_interval)

class SecondWindow(Screen):

    def reduce_clock_interval(self):
        MainWindow.clock_interval -= 1
        MainWindow.clock.cancel()
        MainWindow.clock = Clock.schedule_interval(MainWindow.btn(), self.clock_interval)

class WindowManager(ScreenManager):
    pass

kv = Builder.load_file("my.kv")

class MyApp(App):
    def build(self):
        return kv

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

2 .kv

ScreenManager:
    MainWindow:
    SecondWindow:

<MainWindow>:
    name: "main"
    value: value
    BoxLayout:
        cols: 2
        Button:
            text: "Screen 2"
            on_release:
                app.root.current = "second"

<SecondWindow>:
    name: "second"
    BoxLayout:
        cols: 2

        Button:
            text: "update clock"
            on_press: root.reduce_clock_interval()

        Button:
            text: "Screen 1"
            on_release:
                app.root.current = "main"

Upvotes: 1

Views: 839

Answers (2)

John Anderson
John Anderson

Reputation: 39012

In your edited post, you are trying to access the clock as a class attribute, but it is an instance attribute. Here is a corrected version of reduce_clock_interval():

def reduce_clock_interval(self):
    main_window = App.get_running_app().root.get_screen('main')
    MainWindow.clock_interval -= 1
    main_window.clock.cancel()
    main_window.clock = Clock.schedule_interval(main_window.btn, MainWindow.clock_interval)

Upvotes: 1

John Anderson
John Anderson

Reputation: 39012

You can do what you want by keeping a reference to the Clock event like this:

class MainWindow(Screen):

    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)
        # save a reference to the event
        self.clock = Clock.schedule_interval(self.btn, player.clock_interval)

    def reduce_clock_interval(self):
        player.clock_interval -= 1
        self.clock.cancel()  # cancel the saved event
        # create a new event
        self.clock = Clock.schedule_interval(self.btn, player.clock_interval)

Upvotes: 1

Related Questions