Kivy:将工具栏与屏幕管理器一起使用。我在这里做错了什么?



所以我有一个工具栏,在单个屏幕上运行良好,但我需要两个屏幕。一个主屏幕和一个设置屏幕。我希望使用ScreenManager应该很容易完成。

当我运行此代码时,出现以下错误: 属性错误:"超级"对象没有属性">getattr" 我做错了什么?

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()方法返回来自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(),它得到mainScreen(因为那是包含tool1id的那个)。最后使用该id来获取对MDToolbar的引用。

相关内容

最新更新