KivyMD出现AttributeError报错:'super'对象无'__getattr__'属性求助
错误原因分析
- IDS获取路径错误:根控件
ScreenManager的ids集合中不存在tool1,tool1是嵌套在HomePage、SecondPage内部的MDTopAppBar控件ID,根控件无法直接访问子Screen内部的控件ID。 - 初始化时机过早:在
__init__方法中创建MDDropdownMenu时,KV文件加载的控件树还未完成初始化,此时尝试获取caller会触发属性错误。 - KV语法错误:
right_action_items的格式错误,正确格式应为[['图标名称', 回调函数]],原代码中将图标和回调拆成了两个列表元素,导致逻辑失效。 - Build方法冗余:在
build中创建了新的ScreenManager但未使用,直接返回预加载的self.screen,逻辑混乱。
修正后的实现方案
1. 调整菜单创建时机
将MDDropdownMenu的创建移至on_start方法,此时所有控件已完成初始化,可正确获取目标控件。
2. 正确获取Caller
通过当前活动Screen获取内部的tool1控件,后续菜单弹出时会自动适配点击的工具栏控件。
3. 修复KV语法错误
修正right_action_items的格式,确保图标和回调在同一个列表元素中。
4. 清理冗余代码
移除build方法中未使用的ScreenManager创建代码。
修正后的Python代码
from kivymd.app import MDApp from kivy.lang import Builder from kivymd.uix.menu import MDDropdownMenu from kivy.metrics import dp from kivy.core.window import Window Window.size = (500, 800) class HomePage(): pass class SecondPage(): pass class App(MDApp): def __init__(self, **kwargs): super().__init__(**kwargs) self.screen = Builder.load_file("kivy.kv") self.menu = None def on_start(self): # 初始化下拉菜单,此时控件已全部加载完成 items_d = ['Settings', 'Profile', 'Log Out', 'Exit'] menu_items = [ { "text": f"{i}", "viewclass": "OneLineListItem", "height": dp(40), "on_release": lambda x=f"{i}": self.menu_callback(x), } for i in items_d ] # 获取初始页面的工具栏作为菜单默认调用者 self.menu = MDDropdownMenu( caller=self.screen.get_screen('first').ids.tool1, items=menu_items, width_mult=2 ) def menu_callback(self, text_item): print(text_item) self.menu.dismiss() def build(self): self.theme_cls.primary_palette = 'Red' self.theme_cls.primary_hue = '500' self.theme_cls.theme_style = 'Dark' return self.screen App().run()
修正后的KV文件
#:kivy 2.1.0 ScreenManager: HomePage: SecondPage: <HomePage@Screen> name: 'first' MDNavigationLayout: ScreenManager: Screen: BoxLayout: orientation:'vertical' MDTopAppBar: id:tool1 title: 'Home Page' left_action_items: [['menu', lambda x: nav_drawer.set_state('toggle')]] # 修复right_action_items格式:图标和回调在同一个列表内 right_action_items: [['dots-vertical', lambda x: app.menu.open()]] elevation: 3 MDLabel: text: "Home Page Content" MDBottomAppBar: MDTopAppBar: icon: 'apps' mode: 'center' type: 'bottom' MDNavigationDrawer: id: nav_drawer ScrollView: MDList: OneLineIconListItem: text: 'Home Page' on_press: nav_drawer.set_state('close') root.manager.current = 'first' IconLeftWidgetWithoutTouch: icon:'bluetooth' OneLineIconListItem: text: 'Content Page' on_press: root.manager.current = 'second' nav_drawer.set_state('close') IconLeftWidgetWithoutTouch: icon:'content-copy' <SecondPage@Screen> name: 'second' MDNavigationLayout: ScreenManager: Screen: BoxLayout: orientation:'vertical' MDTopAppBar: id:tool1 title: 'Content Page' left_action_items: [['menu', lambda x: nav_drawer.set_state('toggle')]] right_action_items: [['dots-vertical', lambda x: app.menu.open()]] elevation: 3 MDLabel: text: "Second Page Content" MDBottomAppBar: MDTopAppBar: type: 'bottom' icon: 'apps' mode: 'center' left_action_items: [['information']] MDNavigationDrawer: id: nav_drawer ScrollView: MDList: OneLineIconListItem: text: 'Home Page' on_press: nav_drawer.set_state('close') root.manager.current = 'first' IconLeftWidgetWithoutTouch: icon:'bluetooth' OneLineIconListItem: text: 'Second Page' on_press: nav_drawer.set_state('close') root.manager.current = 'second' IconLeftWidgetWithoutTouch: icon:'wifi'
内容的提问来源于stack exchange,提问作者meelioo
相关产品推荐
相关产品推荐

