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

Kivy与KivyMD向列表添加组件报AttributeError修复方案

报错根因

Kivy/KivyMD触发AttributeError: 'super' object has no attribute '__getattr__',本质是调用ids取控件时,目标id不在当前作用域的ids映射表中,常见触发场景:

  • 操作ids的时机过早,kv布局文件还没完成渲染挂载,ids字典还未生成对应键值
  • id拼写错误、大小写不匹配
  • 目标控件定义在嵌套子容器(比如Screen、弹窗、自定义组件)的kv作用域下,直接从App根节点的ids中查找无法命中
修复方案

1. 调整操作时机

不要在__init__、build()方法执行阶段直接操作ids,这一阶段kv树还未完成挂载,必须将批量添加条目的逻辑挪到on_start生命周期钩子中执行,该钩子触发时整个kv布局已经完全加载,ids映射表可用。
错误示例(禁止写法):

class MainApp(MDApp):
    def build(self):
        self.theme_cls.primary_palette = "Blue"
        # 此处kv尚未加载完成,ids为空,调用必报错
        for i in range(10):
            self.root.ids.List_setting.add_widget(OneLineListItem(text=f"条目{i}"))
        return Builder.load_file("kv_main.kv")

正确写法:

class MainApp(MDApp):
    def build(self):
        self.theme_cls.primary_palette = "Blue"
        return Builder.load_file("kv_main.kv")
    
    def on_start(self):
        # 调试阶段可先打印所有可用id,确认目标id存在
        # print(self.root.ids.keys())
        setting_list = self.root.ids.List_setting
        for i in range(10):
            setting_list.add_widget(
                OneLineListItem(
                    text=f"设置项 {i+1}",
                    on_press=lambda x, idx=i: self.handle_item_press(idx)
                )
            )
    
    def handle_item_press(self, item_index):
        print(f"触发第{item_index+1}项的点击事件")

2. 修正id查找路径

Kivy的ids是按kv根节点做作用域隔离的,如果你的List_setting定义在ScreenManager下属的Screen、自定义弹窗、自定义组件内部,不能直接从self.root.ids查找,需要先定位到持有该id的直接父容器:

示例:如果List_setting写在name为setting_screen的Screen下,查找方式如下

# 先拿到ScreenManager实例,再取对应Screen,最后拿目标id
setting_list = self.root.ids.screen_manager.get_screen("setting_screen").ids.List_setting

3. 基础排查清单

  • 核对kv文件中目标控件的id拼写,和代码中调用的List_setting大小写完全一致,Kivy的id大小写敏感
  • 检查List_setting是否写在<自定义组件名>的kv模板规则中,模板内定义的id不会出现在实例的ids映射表中
  • 动态加载kv的场景下,要等Builder返回的根节点挂载到窗口后再操作ids
代码优化建议
  • 列表条目超过20个时,不要直接循环add_widget堆叠MDList项,改用RecycleView实现列表,滚动流畅度会提升数倍,避免内存占用过高
  • 统一id命名规范,使用小写下划线格式(比如list_setting),和Kivy官方编码风格保持一致,降低拼写错误概率
  • 操作ids前增加存在性判断,减少调试阶段的报错中断:
if "List_setting" in self.root.ids:
    # 执行添加逻辑
else:
    print("当前根节点可用id:", list(self.root.ids.keys()))
  • 列表项的事件回调单独抽成类方法,不要在循环内写过长的匿名函数,降低后期维护成本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:01:08