Kivy:将 Toolbar 与 ScreenManager 一起使用。我在这里做错了什么?

Kivy: Using Toolbar together with ScreenManager. What I'm doing wrong here?

所以我有一个在单个屏幕上运行良好的工具栏,但我需要两个屏幕。一个主屏幕和一个设置屏幕。我希望使用 ScreenManager 可以轻松完成此操作。

当我 运行 这段代码时,我得到以下错误: AttributeError: 'super' object has no attribute 'getattr' What我做错了吗?

from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.menu import MDDropdownMenu
from kivy.metrics import dp

kv = """
ScreenManager:
    MainScreen:
    SetupScreen:

<MainScreen>:
    name: 'main'    

    MDToolbar:
        id: tool1
        title:'My Demo App'
        pos_hint:{'top':1}
        right_action_items : [["dots-vertical", lambda x: app.menu.open()]]

<SetupScreen>:
    name: 'setup'            
"""


class MainScreen(Screen):
    pass


class SetupScreen(Screen):
    pass


# Create the screen manager
sm = ScreenManager()
sm.add_widget(MainScreen(name='main'))
sm.add_widget(SetupScreen(name='setup'))


class DemoApp(MDApp):

    def build(self):
        screen = Builder.load_file('test.kv')
        menu_items = [
            {
                "text": f"Option {opt}",
                "viewclass": "OneLineListItem",
                "height": dp(40),
                "on_release": lambda x=f"Option {opt}": self.menu_callback(x),
            } for opt in range(4)
        ]

        menu = MDDropdownMenu(
            caller=sm.ids.tool1,
            items=menu_items,
            width_mult=3
        )
        return screen


    def menu_callback(self, text_item):
        print(text_item)


DemoApp().run()

我在很多帖子中都看到了同样的错误。当您的 build() 方法 returns 来自 Builder.load_file()Builder.load_string() 的结果时,您的根小部件(以及您的整个 GUI)在 kv 中定义。所以行:

# Create the screen manager
sm = ScreenManager()
sm.add_widget(MainScreen(name='main'))
sm.add_widget(SetupScreen(name='setup'))

正在创建您的 GUI 的另一个实例,但未使用该实例,并且对该 sm 的任何引用都不会影响实际在您的 GUI 中的 ScreenManager(那个通过 kv 构建)。因此,您可以从完全消除这些行开始。

然后,要解决实际问题,您需要将 MDDropdownMenu 的结构更改为:

    self.menu = MDDropdownMenu(
        # caller=sm.ids.tool1,
        caller=screen.get_screen('main').ids.tool1,
        items=menu_items,
        width_mult=3
    )

使用 self.menu 而不是 menu 保存对 menu 的引用。否则,创建 menu,然后丢弃。由于 sm 不是您的 GUI 的一部分,您必须使用对实际 GUI 的引用。该行:

    caller=screen.get_screen('main').ids.tool1,

使用由 Builder 返回的 ScreenMananger (screen)。然后使用 get_screen(),它得到 main Screen(因为那是包含 tool1 id 的那个)。最后使用 id 获取对 MDToolbar.

的引用