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

Kivy添加MDNavigationDrawer后触发TypeError错误的解决求助

解决KivyMD中添加MDNavigationDrawer引发的TypeError错误

我来帮你排查并解决这个TypeError问题,咱们一步步拆解问题并修正:

错误原因分析

从错误日志和你的代码来看,问题出在KV语言的语法错误和MDNavigationDrawer的使用方式不正确:

  1. MDNavigationDrawer不能直接作为根组件:它必须嵌套在MDNavigationLayout容器中,配合顶部导航栏或其他触发控件使用。
  2. KV事件处理语法错误:你在OneLineListItem的on_press后面写了两行代码,但没有把它们放在同一个代码块里,导致KV解析器误把第二行当成了一个无效的属性,最终抛出TypeError: 'NoneType' object is not subscriptable。
  3. 未正确使用自定义的ContentNavigationDrawer:你定义了这个类,但在KV中没有关联它,抽屉内容应该放在这个类里来关联ScreenManager。

修正后的完整代码

下面是修复后的完整代码,我已经调整了布局结构、修正了语法错误,并添加了合理的交互逻辑:

from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen

class mainwin(ScreenManager):
    pass
class AppScreenOne(Screen):
    pass
class User1(Screen):
    pass
class User2(Screen):
    pass

class ContentNavigationDrawer(BoxLayout):
    screen_manager = ObjectProperty()
    nav_drawer = ObjectProperty()

KV = '''
<ContentNavigationDrawer>:
    screen_manager: screen_manager
    nav_drawer: nav_drawer

    ScrollView:
        MDList:
            OneLineListItem:
                text: "Chats"
                on_press: 
                    root.nav_drawer.set_state("close")
                    root.screen_manager.current = "main"

MDNavigationLayout:
    MDNavigationDrawer:
        id: nav_drawer
        ContentNavigationDrawer:
            screen_manager: screen_manager

    ScreenManager:
        id: screen_manager
        AppScreenOne:
        User1:
        User2:

<AppScreenOne>:
    name:'main'
    MDTopAppBar:
        title: "Main Screen"
        left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
        pos_hint: {"top": 1}
    MDFloatingActionButton:
        icon: "android"
        md_bg_color: app.theme_cls.primary_color
        pos_hint: {"x":0.45, "y":0.05}
    ScrollView:
        MDList:
            OneLineAvatarIconListItem:
                text: "User1"
                on_release: app.root.ids.screen_manager.current = "userone"
                IconLeftWidget:
                    icon: "github"
            OneLineAvatarIconListItem:
                text: "User2"
                on_release: app.root.ids.screen_manager.current = "usertwo"
                IconLeftWidget:
                    icon: "gitlab"

<User1>:
    name:"userone"
    MDTopAppBar:
        title: "User1 Chat"
        left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
        pos_hint: {"top": 1}
    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'bottom'
        MDTextField:
            hint_text: "Message"
            mode: "fill"
            fill_color: 0, 0, 0,.4
            max_text_length: 5
            size_hint: (0.7, 0.1)
    AnchorLayout:
        anchor_x: 'right'
        anchor_y: 'bottom'
        MDRaisedButton:
            text: "Send"
            md_bg_color: 0, 0, 0, 1
            size_hint:(0.3, 0.1)

<User2>:
    name:"usertwo"
    MDTopAppBar:
        title: "User2 Chat"
        left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
        pos_hint: {"top": 1}
    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'bottom'
        MDTextField:
            hint_text: "Message"
            mode: "fill"
            fill_color: 0, 0, 0,.4
            max_text_length: 5
            size_hint: (0.7, 0.1)
    AnchorLayout:
        anchor_x: 'right'
        anchor_y: 'bottom'
        MDRaisedButton:
            text: "Send"
            md_bg_color: 0, 0, 0, 1
            size_hint:(0.3, 0.1)
'''

class MainApp(MDApp):
    def build(self):
        return Builder.load_string(KV)

MainApp().run()

关键修正点说明

  • 根布局改为MDNavigationLayout:这是MDNavigationDrawer的标准容器,它包含抽屉区域和主内容区域(你的ScreenManager)。
  • 修复on_press代码块:把原来的两行操作放在同一个on_press:下面,用缩进换行,确保KV解析器能正确识别为一个事件处理逻辑。
  • 关联ContentNavigationDrawer:将抽屉内容放到自定义的ContentNavigationDrawer中,通过ObjectProperty绑定ScreenManager和抽屉控件,方便在抽屉中切换屏幕和控制抽屉开关。
  • 添加MDTopAppBar:给每个屏幕添加顶部导航栏,通过左侧的菜单按钮触发抽屉打开,让交互更符合Material Design规范。
  • 修正屏幕切换路径:原来的app.root.current改为app.root.ids.screen_manager.current,因为现在ScreenManager是MDNavigationLayout的子组件,需要通过id来访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:27:45