简体   繁体   English

具有预定义布局的Python Kivy屏幕管理器不起作用

[英]Python Kivy Screen manager with predefined Layout doesn't work

My Main class returns a instance of ScreenManager. 我的Main类返回ScreenManager的实例。 This ScreenManager has a widget with a Screen class, and I want this Screen class to use a widget which is a Layout that I defined earlier. 这个ScreenManager有一个带有Screen类的窗口小部件,我希望这个Screen类使用一个窗口小部件,它是我之前定义的Layout。

When I execute the code, it only show a black screen with no more information. 当我执行代码时,它只显示黑屏,没有更多信息。 It should show a Button instead. 它应该显示一个按钮。

This is my file minimum.py : 这是我的文件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()

And this is my file testmain.kv : 这是我的文件testmain.kv

<LayoutWithButton>:
    Button:
        text: 'hello'

Even so, if I replace the line self.add_widget(button_layout) of the class MainScreenApp with the line self.add_widget(Button()) it works well. 即便如此,如果我将类MainScreenApp的self.add_widget(button_layout)行替换为self.add_widget(Button())则效果很好。

What am I doing wrong? 我究竟做错了什么?

The problem is that kv file is not loaded until TestMainApp is initialized. 问题是在初始化TestMainApp之前,不会加载kv文件。 As you instanciate MainScreenApp before this, the rules defined within the kv have no effect. 在此之前实例化MainScreenApp ,kv中定义的规则无效。

A very simple solution is to move instanciation of MainScreenApp to App subclass: 一个非常简单的解决方案是将MainScreenApp实例MainScreenApp App子类:

class MainApp(App):

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

You can also force the kv load before instantiating: 您还可以在实例化之前强制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()

Another option is do everything in your kv: 另一种选择是在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: maintest.kv:

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

<MainScreenApp@Screen>:
    LayoutWithButton:

<RootWidget>:
    MainScreenApp:
        name: "main"

From testmain.kv you should remove that < and > from the class name. 从testmain.kv中,您应该从类名中删除该<和>。 You only use it when you are styling it and will also be calling it many many times. 您仅在样式设计时使用它,并且还会多次调用它。

Example how your code should look like: 示例您的代码应如下所示:

 LayoutWithButton: Button: text: 'hello' 

When to use < and >: 何时使用<和>:

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

BoxLayout:
    LayoutWithButton:
         pos_hint: 0, .5

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM