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

KivyMD初始化MDDropdownMenu时出现KeyError: 'dev_button'问题求助

解决MDDropdownMenu初始化时的KeyError: 'dev_button'问题

你遇到的这个KeyError: 'dev_button'其实是Kivy组件加载顺序的典型问题,我来给你拆解清楚:

问题根源

在RootLay的__init__方法执行时,kv文件里定义的dev_button还没被加载到self.ids字典中。Kivy的执行逻辑是:先运行Python类的__init__方法,之后才会解析对应的kv文件并填充ids字典。所以你在__init__里直接访问self.ids.dev_button,自然会找不到这个控件,抛出KeyError。

两种可行的解决方案

方案1:用Clock.schedule_once延迟初始化菜单

把菜单的初始化逻辑延迟到下一帧执行,此时kv已经完成解析,self.ids里就有dev_button了:

修改你的indexui.py代码:

from kivy.clock import Clock  # 先导入Clock

class RootLay(FloatLayout):
    # ... 保留你原有的属性定义 ...

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.device = None
        self.pattern = re.compile(r'[GNSTUkg,\s]')
        self.dev_list = []
        # 这里只定义菜单数据,把初始化逻辑放到延迟函数里
        self.menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
        print(dir(self.ids))  # 现在打印的话,ids里还没有dev_button
        # 延迟一帧执行菜单初始化
        Clock.schedule_once(self._init_menu)

    def _init_menu(self, dt):
        # 此时kv已经解析完成,能正常访问self.ids.dev_button了
        self.menu = MDDropdownMenu(
            caller=self.ids.dev_button,
            items=self.menu_items,
            width_mult=4
        )
        self.menu.bind(on_release=self.menu_callback)
    
    def menu_callback(self, menu, item):
        # 这里可以添加菜单点击后的逻辑,比如选择设备
        print(f"Selected item: {item.text}")
        menu.dismiss()

方案2:重写on_kv_post方法

Kivy提供了on_kv_post生命周期方法,它会在当前类对应的kv文件完全加载解析完成后被调用,非常适合用来做需要访问ids的初始化操作:

修改indexui.py:

class RootLay(FloatLayout):
    # ... 保留你原有的属性定义 ...

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.device = None
        self.pattern = re.compile(r'[GNSTUkg,\s]')
        self.dev_list = []
        self.menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)]
        print(dir(self.ids))

    def on_kv_post(self, base_widget):
        # 当kv加载完成后自动调用这个方法
        super().on_kv_post(base_widget)
        self.menu = MDDropdownMenu(
            caller=self.ids.dev_button,
            items=self.menu_items,
            width_mult=4
        )
        self.menu.bind(on_release=self.menu_callback)
    
    def menu_callback(self, menu, item):
        print(f"Selected item: {item.text}")
        menu.dismiss()

额外说明

你之前用Spinner没问题,大概率是因为Spinner的初始化没有在__init__里直接依赖ids,而是通过kv绑定或者后续事件触发的,避开了加载顺序的问题。

用上面两种方案中的任意一种,都能解决你的KeyError问题,之后点击SEE DEVICES按钮就能正常弹出MDDropdownMenu了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:57:54