Kivy添加MDNavigationDrawer后触发TypeError错误的解决求助
我来帮你排查并解决这个TypeError问题,咱们一步步拆解问题并修正:
错误原因分析
从错误日志和你的代码来看,问题出在KV语言的语法错误和MDNavigationDrawer的使用方式不正确:
- MDNavigationDrawer不能直接作为根组件:它必须嵌套在
MDNavigationLayout容器中,配合顶部导航栏或其他触发控件使用。 - KV事件处理语法错误:你在
OneLineListItem的on_press后面写了两行代码,但没有把它们放在同一个代码块里,导致KV解析器误把第二行当成了一个无效的属性,最终抛出TypeError: 'NoneType' object is not subscriptable。 - 未正确使用自定义的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
相关产品推荐
相关产品推荐

