BoxLayout 中的 Kivy 嵌套 ScreenManager

Kivy Nested ScreenManager inside BoxLayout

每周都会看到不同风格的东西,我们又来了更多 ScreenManager 恶作剧!

除非按钮是屏幕本身的一部分,否则屏幕不会改变,我想要一个顶部的通用导航栏,然后在它下面有一个“显示”。两个屏幕都可以,但切换按钮不行。

(如果你能告诉我如何让每个屏幕都有自己的 KV 文件,并且仍然 link 使用屏幕管理器,加分)

无论如何:代码

QCManager.py

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition

kivy.require('1.9.1')


class MOTD(Screen):
    print("MOTD Screen!")
    pass


class Search(Screen):
    print("Search Screen!")
    pass


class ScreenManagement(ScreenManager):
    pass


class ClassAllScreen(BoxLayout):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.manager = ScreenManagement()


class ClassApp(App):

    def build(self):
        self.root = ClassAllScreen()
        return self.root

if __name__ == '__main__':
    Builder.load_file('./kvfiles/main.kv')
    ClassApp().run()

main.kv

#: import NoTransition kivy.uix.screenmanager.NoTransition
<MOTD>:
    name: 'motd'
    BoxLayout:
        orientation:'vertical'
        padding:20
        spacing:10
        Label:
            text:"The Cake Is a Lie"

<Search>:
    name: 'search'
    BoxLayout:
        orientation:'vertical'
        padding:20
        spacing:10
        GridLayout:
            spacing:10
            cols:2

            Button:
                text:'Left'
            Button:
                text:'Right'
        Button:
            text:'bottom'


<ScreenManagement>:
    transition: NoTransition()
    MOTD:
    Search:

<ClassAllScreen>:
    orientation:'vertical'
    BoxLayout:
        size_hint_y: None
        height: 60
        spacing: 5
        padding: 5

        canvas:
            Color:
                rgba: .1,.1,.1,1
            Rectangle:
                pos: self.pos
                size: self.size
        Button:
            text:'Menu'
            size_hint_x: None
            width: 120
            on_release: root.manager.current = 'motd'
        Button:
            text:'Search'
            size_hint_x: None
            width: 120
            on_release: root.manager.current = 'search'
        Button:
            text:'Add to DB'
            size_hint_x: None
            width: 120
            on_press: print("Button Working")
    ScreenManagement:

__init__() ClassAllScreen class 中的方法正在创建 ScreenManagement 的实例。该实例保存为 self.manager,但未添加到您的 GUI。

在您的 kv 文件中,行:

ScreenManagement:

正在创建另一个不同的 ScreenManagement 实例。此 ScreenManagement 实例是您的 GUI 中的实例。

因此,您在 ClassAllScreen 中对 self.manager 所做的任何操作都不会影响 GUI 中的 ScreenManagement

解决方法是确保您引用 ScreenManagement 的正确实例(而不是创建任何其他实例)。为此,您可以在 kv 文件中将 ObjectProperty 添加到 ClassAllScreen,如下所示:

<ClassAllScreen>:
    manager: scr_manager  # added ObjectProperty that references the scr_manager id
    orientation:'vertical'
    BoxLayout:
        size_hint_y: None
        height: 60
        spacing: 5
        padding: 5

        canvas:
            Color:
                rgba: .1,.1,.1,1
            Rectangle:
                pos: self.pos
                size: self.size
        Button:
            text:'Menu'
            size_hint_x: None
            width: 120
            on_release: root.manager.current = 'motd'
        Button:
            text:'Search'
            size_hint_x: None
            width: 120
            on_release: root.manager.current = 'search'
        Button:
            text:'Add to DB'
            size_hint_x: None
            width: 120
            on_press: print("Button Working")
    ScreenManagement:
        id: scr_manager  # new id to enable reference to this ScreenManagement instance

然后ClassAllScreen class可以简化为:

class ClassAllScreen(BoxLayout):
    pass

只是为了帮助任何尝试做同样事情的人。固定代码如下

App.py

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition

kivy.require('1.9.1')


class MOTD(Screen):
    print("MOTD Screen!")
    pass


class Search(Screen):
    print("Search Screen!")
    pass


# class ScreenManagement(ScreenManager):
    # pass  # Removed, Instanced in kv


class ClassAllScreen(BoxLayout):
    pass  # Removed code, Done in kv


class ClassApp(App):
    def build(self):
        self.root = ClassAllScreen()
        return self.root

if __name__ == '__main__':
    Builder.load_file('./kvfiles/main.kv')
    ClassApp().run()

main.kv

#: import NoTransition kivy.uix.screenmanager.NoTransition
<MOTD>:
    name: 'motd'
    BoxLayout:
        orientation:'vertical'
        padding:20
        spacing:10
        Label:
            text:"The Cake Is a Lie"

<Search>:
    name: 'search'
    BoxLayout:
        orientation:'vertical'
        padding:20
        spacing:10
        GridLayout:
            spacing:10
            cols:2

            Button:
                text:'Left'
            Button:
                text:'Right'
        Button:
            text:'bottom'


<ClassAllScreen>:
    manager:scr_manager
    orientation:'vertical'
    BoxLayout:
        size_hint_y: None
        height: 60
        spacing: 5
        padding: 5

        canvas:
            Color:
                rgba: .1,.1,.1,1
            Rectangle:
                pos: self.pos
                size: self.size
        Button:
            text:'Menu'
            size_hint_x: None
            width: 120
            on_release: root.manager.current = 'motd'
        Button:
            text:'Search'
            size_hint_x: None
            width: 120
            on_release: root.manager.current = 'search'
        Button:
            text:'Add to DB'
            size_hint_x: None
            width: 120
            on_press: print("Button Working")
    ScreenManager:
        transition: NoTransition()
        id: scr_manager
        MOTD:
        Search: