You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

关键修改点

  1. 将MDNavigationLayout设为根布局,直接通过self.root.ids.nav_drawer获取抽屉控件,简化层级结构。
  2. 删除MDNavigationDrawer上的on_release事件,避免拦截内部item的点击事件。
  3. 在MDNavigationDrawerItem的on_release中添加关闭抽屉的逻辑,切换屏幕后自动关闭抽屉,提升交互体验。
  4. 移除原代码中用于测试的抽屉外冗余控件(若需保留可自行添加,注意控件id不可重复)。

内容的提问来源于stack exchange,提问作者UncleB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 18:44:50