Kivy通过id向GridLayout添加按钮报super无__getattr__错误
问题现象
开发Kivy应用时,尝试通过id向指定GridLayout控件动态添加按钮,预期在id为grids的GridLayout中生成10个按钮,实际运行抛出AttributeError: 'super' object has no attribute '__getattr__'异常,逻辑未按预期执行。
问题产生原因
核心触发原因是违反了Kivy的id作用域规则,附带2个会影响功能运行/代码规范性的问题:
- Kivy中每个控件的
self.ids字典,仅存储当前控件直接子层级、带id标识的控件,嵌套在更深层级子控件内部的id,不会注册到上层控件的ids表中。查看kv文件的控件层级:MainScreen的直接子控件只有id为box1的外层GridLayout,因此MainScreen的self.ids中仅存在box1这一个键- id为
grids的GridLayout是scrolls(ScrollView控件)的直接子控件,仅会被注册到scrolls的ids表中
直接在MainScreen实例上访问self.ids.grids属于访问不存在的字典键,会触发Kivy内部属性查找逻辑抛出上述AttributeError。
- main.py中重复定义了两次
RootWidget类,属于冗余无效代码,虽不直接触发本次报错,但不符合编码规范。 - ScrollView内的GridLayout未配置高度自适应规则,即使解决id访问问题,动态添加的按钮也无法正常显示、ScrollView无法触发滚动。同时ScrollView控件本身没有
spacing属性,原kv中在ScrollView上写的spacing配置不生效。
解决方案
按以下步骤修改即可解决问题:
- 修正id访问路径,顺着控件层级查找目标GridLayout,不要跨层级直接访问深层id。将
MainScreen类中on_enter方法的逻辑修改为:
class MainScreen(Screen): def on_enter(self): # 按控件层级找到目标grids控件 target_grid = self.ids.box1.ids.scrolls.ids.grids for i in range(10): button = RoundedButton(text=f"测试按钮{i+1}") # 给动态按钮设置固定高度,配合滚动布局显示 button.size_hint_y = None button.height = 60 target_grid.add_widget(button)
- 清理冗余代码,删除main.py中
MainApp类定义之后重复的class RootWidget(ScreenManager): pass语句。 - 修改kv文件中ScrollView和内部GridLayout的配置,补全高度自适应规则,将无效的spacing配置移动到GridLayout上:
ScrollView: id: scrolls do_scroll_x:False GridLayout: id: grids cols:1 size_hint_y: None height: self.minimum_height spacing: 10 RoundedButton: text: "hi" size_hint_x: .98 size_hint_y: None height: 60
修改完成后重新运行,即可在目标GridLayout中正常生成10个按钮,ScrollView也可正常滚动浏览所有内容。
内容的提问来源于stack exchange,提问作者Croampers
相关产品推荐
相关产品推荐

