KivyMD 2.0.1中MDNavigationDrawerItem嵌入抽屉后无响应求助
问题描述
我是Kivy和KivyMD新手,遇到一个问题:把MDNavigationDrawerItem放入MDNavigationDrawer后点击无响应,把相同控件放在抽屉外时虽能响应但偶尔失灵。不确定是操作错误还是KivyMD的潜在BUG,求解决。
原代码
main.kv
MDScreen: md_bg_color: self.theme_cls.backgroundColor size: root.width, root.height md_bg_color: "red" MDNavigationLayout: MDScreenManager: id: screen_manager Screen: name: "screen1" md_bg_color: "blue" MDGridLayout: cols: 1 md_bg_color: "green" #orientation: 'vertical' MDTopAppBar: type: "small" elevation: 4 pos_hint: {"top": 1} MDTopAppBarLeadingButtonContainer: MDActionTopAppBarButton: icon: "menu" on_release: app.toggleMenu() MDTopAppBarTitle: text: "AppBar small" halign: "center" MDTopAppBarTrailingButtonContainer: MDActionTopAppBarButton: icon: "account-circle-outline" MDLabel: text: "Screen 1" ####### This is only here to demonstrate that it works outside of the Drawer #### MDNavigationDrawerMenu: id: navmenu2 MDNavigationDrawerItem: on_release: app.changeScreen("screen2") MDNavigationDrawerItemText: text: "Screen 2" ################################################################################# Screen: name: "screen2" md_bg_color: "blue" MDGridLayout: cols: 1 md_bg_color: "red" #orientation: 'vertical' MDTopAppBar: type: "small" elevation: 4 pos_hint: {"top": 1} #left_action_items: #[['menu', lambda x: nav_drawer.set_state("open")]] MDTopAppBarLeadingButtonContainer: MDActionTopAppBarButton: icon: "menu" on_release: app.toggleMenu() MDTopAppBarTitle: text: "AppBar small" halign: "center" MDTopAppBarTrailingButtonContainer: MDActionTopAppBarButton: icon: "account-circle-outline" MDLabel: text: "Screen 2" ####### This is only here to demonstrate that it works outside of the Drawer #### MDNavigationDrawerMenu: id: navmenu2 MDNavigationDrawerItem: on_release: app.changeScreen("screen1") MDNavigationDrawerItemText: text: "Screen 1" ################################################################################# MDNavigationDrawer: id: nav_drawer on_release: lambda x: print("Navigation drawer event") MDNavigationDrawerMenu: MDNavigationDrawerItem: on_release: app.changeScreen("screen1") MDNavigationDrawerItemText: text: "Screen 1" MDNavigationDrawerItem: on_release: app.changeScreen("screen2") MDNavigationDrawerItemText: text: "Screen 2" MDNavigationDrawerDivider:
main.py
#Import dependencies from kivymd.app import MDApp from kivy.lang import Builder #Define main app class class myApp(MDApp): def build(self): return Builder.load_file("main.kv") def toggleMenu(self): self.root.ids.nav_drawer.set_state("toggle") pass def changeScreen(self, screen): print("changeScreen") self.root.ids.screen_manager.current = screen pass #Run if __name__ == "__main__": myApp().run()
问题原因与修复方案
你的代码存在两个核心问题:
- 导航抽屉引用错误:
toggleMenu方法中尝试通过self.root.ids.nav_drawer获取抽屉,但nav_drawer是MDNavigationLayout的子控件,而非根MDScreen的直接子控件,导致该方法实际会抛出属性错误,抽屉的打开/关闭逻辑异常。 - 抽屉
on_release拦截子控件事件:MDNavigationDrawer自身绑定的on_release事件会优先响应点击,覆盖内部MDNavigationDrawerItem的点击事件,导致item无响应。
修复后的代码
main.kv
MDNavigationLayout: id: nav_layout MDScreenManager: id: screen_manager Screen: name: "screen1" md_bg_color: "blue" MDGridLayout: cols: 1 md_bg_color: "green" MDTopAppBar: type: "small" elevation: 4 pos_hint: {"top": 1} MDTopAppBarLeadingButtonContainer: MDActionTopAppBarButton: icon: "menu" on_release: app.toggleMenu() MDTopAppBarTitle: text: "AppBar small" halign: "center" MDTopAppBarTrailingButtonContainer: MDActionTopAppBarButton: icon: "account-circle-outline" MDLabel: text: "Screen 1" Screen: name: "screen2" md_bg_color: "blue" MDGridLayout: cols: 1 md_bg_color: "red" MDTopAppBar: type: "small" elevation: 4 pos_hint: {"top": 1} MDTopAppBarLeadingButtonContainer: MDActionTopAppBarButton: icon: "menu" on_release: app.toggleMenu() MDTopAppBarTitle: text: "AppBar small" halign: "center" MDTopAppBarTrailingButtonContainer: MDActionTopAppBarButton: icon: "account-circle-outline" MDLabel: text: "Screen 2" MDNavigationDrawer: id: nav_drawer MDNavigationDrawerMenu: MDNavigationDrawerItem: on_release: app.changeScreen("screen1") nav_drawer.set_state("close") MDNavigationDrawerItemText: text: "Screen 1" MDNavigationDrawerItem: on_release: app.changeScreen("screen2") nav_drawer.set_state("close") MDNavigationDrawerItemText: text: "Screen 2" MDNavigationDrawerDivider:
main.py
# Import dependencies from kivymd.app import MDApp from kivy.lang import Builder # Define main app class class myApp(MDApp): def build(self): return Builder.load_file("main.kv") def toggleMenu(self): self.root.ids.nav_drawer.set_state("toggle") def changeScreen(self, screen): print("changeScreen") self.root.ids.screen_manager.current = screen # Run if __name__ == "__main__": myApp().run()
关键修改点
- 将
MDNavigationLayout设为根布局,直接通过self.root.ids.nav_drawer获取抽屉控件,简化层级结构。 - 删除
MDNavigationDrawer上的on_release事件,避免拦截内部item的点击事件。 - 在
MDNavigationDrawerItem的on_release中添加关闭抽屉的逻辑,切换屏幕后自动关闭抽屉,提升交互体验。 - 移除原代码中用于测试的抽屉外冗余控件(若需保留可自行添加,注意控件id不可重复)。
内容的提问来源于stack exchange,提问作者UncleB
相关产品推荐
相关产品推荐

