Python 带有预定义布局的 Kivy 屏幕管理器不工作

Python Kivy Screen manager with predefined Layout doesn't work

My Main class returns ScreenManager 的一个实例。这个 ScreenManager 有一个带有 Screen class 的小部件,我希望这个 Screen class 使用一个我之前定义的 Layout 小部件。

当我执行代码时,它只显示黑屏,没有更多信息。它应该显示一个按钮。

这是我的文件minimum.py:

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

class LayoutWithButton(BoxLayout):

    def __init__(self, **kwargs):
        super(LayoutWithButton, self).__init__(**kwargs)

class MainScreenApp(Screen):

    def __init__(self, **kwargs):
        super(MainScreenApp, self).__init__(**kwargs)
        button_layout = LayoutWithButton()
        self.add_widget(button_layout)

screen_manager = ScreenManager()
screen_manager.add_widget(MainScreenApp(name='main'))

class TestMainApp(App):

    def build(self):
        return screen_manager

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

这是我的文件testmain.kv:

<LayoutWithButton>:
    Button:
        text: 'hello'

即便如此,如果我将 class MainScreenApp 的 self.add_widget(button_layout) 行替换为 self.add_widget(Button()) 行,它也能正常工作。

我做错了什么?

从 testmain.kv 开始,您应该从 class 名称中删除 < 和 >。 您仅在设置样式时使用它,并且还会多次调用它。

您的代码的示例:

LayoutWithButton:
     Button:
          text: 'hello'

何时使用 < 和 >:

<LayoutWithButton>:
      pos_hint: 0, .5
      Button:
          text: 'hello'

BoxLayout:
    LayoutWithButton:
         pos_hint: 0, .5

祝你好运!

问题是在 TestMainApp 初始化之前不会加载 kv 文件。当您在此之前实例化 MainScreenApp 时,kv 中定义的规则无效。

一个非常简单的解决方案是将 MainScreenApp 的实例移至 App 子类:

class MainApp(App):

    def build(self):
        screen_manager = ScreenManager()
        screen_manager.add_widget(MainScreenApp(name='main'))
        return screen_manager

也可以在实例化之前强制加载kv:

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


class LayoutWithButton(BoxLayout):
    pass


class MainScreenApp(Screen):

    def __init__(self, **kwargs):
        super(MainScreenApp, self).__init__(**kwargs)
        button_layout = LayoutWithButton()
        self.add_widget(button_layout)

Builder.load_file("testmain.kv")
screen_manager = ScreenManager()
screen_manager.add_widget(MainScreenApp(name='main'))


class TestApp(App):

    def build(self):
        return screen_manager


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

另一种选择是在您的 kv 中执行所有操作:

from kivy.uix.screenmanager import ScreenManager
from kivy.app import App


class RootWidget(ScreenManager):
    pass


class MainTestApp(App):
    def build(self):
        return MainWindow()


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

maintest.kv:

<LayoutWithButton@BoxLayout>:
    Button:
        text: 'hello'

<MainScreenApp@Screen>:
    LayoutWithButton:

<RootWidget>:
    MainScreenApp:
        name: "main"