2023年10月18日 星期三

Kivy screen篇 ScreenManager類 講解

簡述

根據官方解釋:

Screen manager. This is the main class that will control your Screen stack and memory.

意思是ScreenManager類被用來管理Screen類,我們通常將設計好的layout與widget放入screen類中,以便screenmanager操作。

ScreenManager繼承自kivy.uix.floatlayout.FloatLayout,因此也是widget類的子類,因此可以使用widget類的所有屬性與方法,在官方文檔介紹ScreenManager類的內容中有大量與widget類的內容重覆,因此本教學只介紹ScreenManager專門的用法,與widget類重疊的內容一律跳過。

基本範例

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

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.properties import ObjectProperty


class AScreen(Screen):
    pass


class BScreen(Screen):
    pass


class sm(ScreenManager):
    a1 = ObjectProperty(SlideTransition(duration=7))


class MyApp(App):

    def build(self):
        return sm()


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

在以上程式碼中,我們在sm類中宣告a1為ObjectProperty,值為SlideTransition(duration=7)(有關Transition在下一篇會介紹)

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

<AScreen>:
    name: 'menu'

    BoxLayout:

        Button:
            text: 'Goto settings'
            on_press: root.manager.current = 'settings'

        Label:
            text: str(root.transition_progress)


<BScreen>:
    name: 'settings'

    BoxLayout:

        Label:
            text: str(root.transition_progress)

        Button:
            text: 'My settings button'
            
        Button:
            text: 'still settings'
            on_press: root.manager.current = 'menu'


<sm>:
    transition: root.a1

    AScreen:

    BScreen:

執行結果如下:

ScreenManager使用技巧:

1(a) current:可以用來決定目前呈現的Screen

1(b) switch_to(screen, **options):可以用來決定跳轉至哪一個Screen

(注意:官方建議以上兩種方式擇一即可,盡量避免混用)

current版本如同基本範例中所示

switch_to版本如下

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

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.properties import ObjectProperty


class AScreen(Screen):

    def btn1(self):
        setting_screen = self.manager.get_screen('settings')
        self.manager.switch_to(setting_screen)


class BScreen(Screen):
    pass


class sm(ScreenManager):
    a1 = ObjectProperty(SlideTransition(duration=5))


class MyApp(App):

    def build(self):
        return sm()


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

在以上程式碼中,我宣告btn1方法的內容為:利用get_screen('settings')來找出name為'setting'的Screen物件並回傳,而後呼叫switch_to(setting_screen)使sm將畫面上的Screen換成name為'setting'的Screen。

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

<AScreen>:
    name: 'menu'

    BoxLayout:

        Button:
            text: 'Goto settings'
            on_press: root.btn1()

        Label:
            text: str(root.transition_progress)


<BScreen>:
    name: 'settings'

    BoxLayout:

        Label:
            text: str(root.transition_progress)

        Button:
            text: 'My settings button'

        Button:
            text: 'still settings'
            on_press: root.manager.current = 'menu'


<sm>:
    transition: root.a1

    AScreen:

    BScreen:

執行結果如下:

2.current_screen:回傳目前Screen物件,此為唯讀,無法更改

3.screen_names:回傳ScreenManager內所有Screen name的串列,此為唯讀,無法更改

4.screens:回傳ScreenManager內所有Screen物件的串列,此為唯讀,無法更改

2、3、4點統一以以下一個例子示範

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

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.properties import ObjectProperty


class AScreen(Screen):
    def btn1(self):
        print(self.manager.current_screen)


class BScreen(Screen):
    pass


class sm(ScreenManager):
    a1 = ObjectProperty(SlideTransition(duration=5))


class MyApp(App):

    def build(self):
        return sm()


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

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

<AScreen>:
    name: 'menu'

    BoxLayout:

        Button:
            text: 'Goto settings'
            on_press: root.btn1()

        Label:
            text: str(root.transition_progress)


<BScreen>:
    name: 'settings'

    BoxLayout:

        Label:
            text: str(root.transition_progress)

        Button:
            text: 'My settings button'

        Button:
            text: 'still settings'
            on_press: root.manager.current = 'menu'


<sm>:
    transition: root.a1

    AScreen:

    BScreen:

執行結果如下:

6.get_screen(name):在ScreenManager中搜尋name=name的Screen物件並回傳此Screen物件,若不存在name=name的Screen物件則回傳錯誤訊息

7.get_screen(name):在ScreenManager中搜尋name=name的Screen物件,若此Screen物件存在則回傳True,若不存在則回傳False

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

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.properties import ObjectProperty


class AScreen(Screen):

    #列印self.manager.get_screen('settings')與(self.manager.has_screen('apple')的回傳值
    def btn1(self):
        print(self.manager.get_screen('settings'))
        print(self.manager.has_screen('apple'))


class BScreen(Screen):
    pass


class sm(ScreenManager):
    a1 = ObjectProperty(SlideTransition(duration=5))


class MyApp(App):

    def build(self):
        return sm()


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

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

<AScreen>:
    name: 'menu'

    BoxLayout:

        Button:
            text: 'Goto settings'
            on_press: root.btn1()

        Label:
            text: str(root.transition_progress)


<BScreen>:
    name: 'settings'

    BoxLayout:

        Label:
            text: str(root.transition_progress)

        Button:
            text: 'My settings button'

        Button:
            text: 'still settings'
            on_press: root.manager.current = 'menu'


<sm>:
    transition: root.a1

執行結果如下:

第二個回傳值為False,因為sm裡面不存在name為apple的Screen

8.transition:決定此ScreenManager切換Screen時的動畫(有關Transition在下一篇會介紹)

沒有留言:

張貼留言

精選文章

Kivy UIX篇 widget篇 TabbedPanel類 event篇 講解