Kivy动态创建按钮实现点击自删除功能的开发问题
问题根因
- Kivy的Property机制仅识别类层级定义的Property对象,存放在普通Python列表内的
ObjectProperty不会被框架注册为可绑定属性,KV解析时无法识别对应引用,必然触发报错。 - KV语法中同个属性不允许重复赋值,原代码循环拼接KV时重复写入
Buttons: Buttons属于语法错误。 - 完全不需要提前声明一堆
ObjectProperty存按钮引用:KV内定义的控件id会自动归集到控件实例的self.ids字典中;更简单的是,按钮的on_release事件触发时,回调的第一个参数就是按钮自身实例,直接用这个实例就能完成删除操作,连索引映射都不需要做。 - 原代码用
StringProperty存放列表数据属于类型错误,列表类型数据需要用ListProperty定义才能被KV正确识别。
可直接运行的修正代码
import kivy from Nils_Programm_verkürzt import lektionstextlesen from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import ListProperty from kivy.lang import Builder # 仅读取一次外部文件,避免类定义、实例化阶段重复IO Inputfile = 'Lektionstext15.txt' ReturnTuple = lektionstextlesen(Inputfile) Satzliste = ReturnTuple[0] Worterliste = ReturnTuple[1] # 基础布局KV kv = """ <Testwidget>: canvas: Rectangle: pos: 0, self.center_y size: self.width, 10 Rectangle: pos: self.pos size: self.size source: 'background.png' """ # 按钮模板,on_release直接传入按钮实例self,不需要绑定id做索引映射 button_tpl = """ Button: text: root.Satzliste[{index}] center_x: root.width / 2 top: root.top - 100 - {offset} font_size: 30 size: self.texture_size on_release: root.delete_btn(self) """ # 循环拼接所有动态按钮的KV定义 for idx, _ in enumerate(Satzliste): kv += button_tpl.format(index=idx, offset=idx*50) Builder.load_string(kv) class Testwidget(Widget): # 列表类型数据用ListProperty声明,保证KV侧可正确读取 Satzliste = ListProperty(Satzliste) Worterliste = ListProperty(Worterliste) def delete_btn(self, btn): # 直接移除传入的按钮实例即可,不需要额外查找引用 self.remove_widget(btn) class GuiApp(App): def build(self): return Testwidget() if __name__ == '__main__': GuiApp().run()
补充说明
- 如果后续需要批量操作所有动态生成的按钮,直接遍历
self.children筛选Button类型实例即可,也可以在控件初始化方法里遍历self.ids把需要的引用存到普通Python列表,不需要为每个按钮单独声明ObjectProperty。 - 如果需要通过id获取指定按钮,只需要在KV里给按钮设置
id: btn_{index},后续直接通过self.ids[f"btn_{index}"]就能拿到对应实例,不需要提前在Python侧做任何声明。
内容的提问来源于stack exchange,提问作者Delicious_pie
相关产品推荐
相关产品推荐

