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
.
的引用
所以我有一个在单个屏幕上运行良好的工具栏,但我需要两个屏幕。一个主屏幕和一个设置屏幕。我希望使用 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
.