2023年11月13日 星期一

kivy clock篇 Clock類 (基礎篇)

簡述

根據官方解釋:

The Clock object allows you to schedule a function call in the future; once or repeatedly at specified intervals.

意思是Clock物件可以安排將來的函數調用; 一次或以指定的時間間隔重複。

基本範例

在main.py中寫上此段程式碼:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock


class MyLayout(GridLayout):
    a1 = ObjectProperty(None)
    count = NumericProperty()

    def btn1(self):
        event = Clock.schedule_once(self.add_count, 2)

    def add_count(self, dt):
        self.count = self.count + 1
        self.a1.text = "past {} second".format(self.count)


class Myapp(App):

    def build(self):
        return MyLayout()


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

在以上程式碼中

(1)宣告a1物件為ObjectProperty類,以便在kv file中與Label連結

(2)宣告count物件為NumericProperty類

(3)在MyLayout中宣告btn1方法,當btn1方法被呼叫時,Clock類呼叫schedule_once方法,使得add_count方法在兩秒後被呼叫(注意:Clock.schedule_once(self.add_count, 2)不寫成Clock.schedule_once(self.add_count(), 2),因為參數要求的是function本身而不是function的return)

(4)在MyLayout中宣告add_count方法(特別注意dt,它是delta time的縮寫,意思是時間變動,在此篇中的所有Clock類的方法的第一個input(也就是要被呼叫的方法),都必須要有dt否則會出錯),當add_count方法被呼叫時,使得新的count為舊的count加一,並且使a1物件的text屬性為"past {} second".format(self.count)

在my.kv中寫上此段程式碼:

<MyLayout>:
    rows:2
    a1: b1

    Label:
        id: b1
        text:'starting point'

    Button:
        text: 'start'
        on_press: root.btn1()

在以上程式碼中

(1)宣告main.py中的a1物件與kv file中id為b1的物件連結

(2)當Button被按下時,呼叫根部件的btn1方法

執行結果如下:

從以上結果可以看出,每當點擊Button時,經過兩秒後數字會加一。

clock使用技巧

1.schedule_once(callback, timeout=0):幾秒後執行一次callback

(基本範例已經示範過)

2.schedule_interval(callback, timeout=0):每幾秒執行一次callback

在main.py中寫上此段程式碼:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock


class MyLayout(GridLayout):
    a1 = ObjectProperty(None)
    count = NumericProperty()

    def btn1(self):
        event = Clock.schedule_interval(self.add_count, 1)

    def add_count(self, dt):
        self.count = self.count + 1
        self.a1.text = "past {} second".format(self.count)


class Myapp(App):

    def build(self):
        return MyLayout()


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

在my.kv中寫上此段程式碼:

<MyLayout>:
    rows:2
    a1: b1

    Label:
        id: b1
        text:'starting point'

    Button:
        text: 'start'
        on_press: root.btn1()

執行結果如下:

從以上結果可以看到,當我點擊Button一次時,每隔一秒Label的數字都會加一;當我繼續點擊Button多次時,Label的數字越加越快,原因是因為每點擊Button一次,"每隔一秒Label的數字都會加一"這個動作會一直疊加。

3.create_trigger(callback, timeout=0, interval=False, release_ref=True):與前兩個不同的是,呼叫create_trigger方法並不會立即呼叫callback

在main.py中寫上此段程式碼:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock


class MyLayout(GridLayout):
    a1 = ObjectProperty(None)
    count = NumericProperty()

    def btn1(self):
        event = Clock.create_trigger(self.add_count)

    def add_count(self, dt):
        self.count = self.count + 1
        self.a1.text = "past {} second".format(self.count)


class Myapp(App):

    def build(self):
        return MyLayout()


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

在my.kv中寫上此段程式碼:

<MyLayout>:
    rows:2
    a1: b1

    Label:
        id: b1
        text:'starting point'

    Button:
        text: 'start'
        on_press: root.btn1()

執行結果如下:

從以上結果可以看到,無論我怎麼點Button,都沒有任何反應。

若將main.py改成

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock


class MyLayout(GridLayout):
    a1 = ObjectProperty(None)
    count = NumericProperty()

    def btn1(self):
        event = Clock.create_trigger(self.add_count)
        event() #多了這行

    def add_count(self, dt):
        self.count = self.count + 1
        self.a1.text = "past {} second".format(self.count)


class Myapp(App):

    def build(self):
        return MyLayout()


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


執行結果如下:

從以上結果可以看到,點擊Button是有反應的。

4.event.cancel():使event的callback不再被調用(注意:這邊是event呼叫cancel方法,可與第五點比較)

在main.py中寫上此段程式碼:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock


class MyLayout(GridLayout):
    a1 = ObjectProperty(None)
    count = NumericProperty()

    def btn1(self):
        global event
        event = Clock.schedule_interval(self.add_count, 1)
        event()

    def add_count(self, dt):
        self.count = self.count + 1
        self.a1.text = "past {} second".format(self.count)

    def btn2(self):
        event.cancel()

class Myapp(App):

    def build(self):
        return MyLayout()


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

在以上的程式碼中,宣告btn2方法的內容為:event物件呼叫cancel方法。

在my.kv中寫上此段程式碼:

<MyLayout>:
    rows:2
    a1: b1

    Label:
        id: b1
        text:'starting point'

    Button:
        text: 'start'
        on_press: root.btn1()

    Button:
        text: 'stop'
        on_press: root.btn2()

執行結果如下:

從以上結果可以看到,當握按下'stop' Button時,數字停止增加了,代表self.add_count不再被調用。

5.Clock.unschedule(event):使event的callback不再被調用(注意:這邊是Clock呼叫unschedule方法,可與第四點比較)

在main.py中寫上此段程式碼:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock


class MyLayout(GridLayout):
    a1 = ObjectProperty(None)
    count = NumericProperty()

    def btn1(self):
        global event
        event = Clock.schedule_interval(self.add_count, 1)
        event()

    def add_count(self, dt):
        self.count = self.count + 1
        self.a1.text = "past {} second".format(self.count)

    def btn2(self):
        Clock.unschedule(event) #與第四點的程式碼只差在這行

class Myapp(App):

    def build(self):
        return MyLayout()


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

在以上的程式碼中,宣告btn2方法的內容為:Clock物件呼叫unschedule()方法,參數為event。

在my.kv中寫上此段程式碼:

<MyLayout>:
    rows:2
    a1: b1

    Label:
        id: b1
        text:'starting point'

    Button:
        text: 'start'
        on_press: root.btn1()

    Button:
        text: 'stop'
        on_press: root.btn2()

執行結果如下:

(4、5點是差不多的東西,擇一使用即可)

沒有留言:

張貼留言

精選文章

Kivy UIX篇 widget篇 TabbedPanel類 event篇 講解