Kivy中add_widget方法内访问子控件属性为空如何解决?
问题原因
KV语言的加载流程是先实例化所有声明的控件对象,再依次为控件设置KV中定义的属性。你重写的add_widget方法是在MDLabel实例化完成后、text属性赋值前被调用的,所以此时读取text自然是空值。另外你当前的代码中,判断是MDLabel类型时没有调用父类的add_widget方法,会导致MDLabel最终不会被添加到CustomWidget中,界面不会显示对应文本。
修复方案
- 方案1:使用
Clock.schedule_once延迟属性访问,等待KV属性赋值完成后再执行逻辑
from kivy.clock import Clock class CustomWidget(BoxLayout): def add_widget(self, widget, index=0, canvas=None): # 先调用父类方法保证控件被正常添加 super(CustomWidget, self).add_widget(widget, index, canvas) if isinstance(widget, MDLabel): # 延迟到下一帧执行,此时KV已完成属性赋值 Clock.schedule_once(lambda dt: self._process_label(widget)) def _process_label(self, label): print("{}'s text is: {}".format(label, label.text))
- 方案2:绑定text属性变化事件,只要text被赋值就触发处理逻辑,适配属性动态修改的场景
class CustomWidget(BoxLayout): def add_widget(self, widget, index=0, canvas=None): super(CustomWidget, self).add_widget(widget, index, canvas) if isinstance(widget, MDLabel): widget.bind(text=self._on_label_text_change) def _on_label_text_change(self, label, new_text): print("{}'s text is: {}".format(label, new_text))
- 方案3:重写
on_kv_post方法,等待当前控件的KV规则全部加载完成后,统一遍历处理所有子控件
class CustomWidget(BoxLayout): def on_kv_post(self, base_widget): super().on_kv_post(base_widget) # 此时所有子控件的KV属性都已赋值完成 for widget in self.walk(): if isinstance(widget, MDLabel): print("{}'s text is: {}".format(widget, widget.text))
以上任意方案都可以正常获取到MDLabel的text属性值,同时保证控件正常渲染到界面。
内容的提问来源于stack exchange,提问作者Omid Ketabollahi
相关产品推荐
相关产品推荐

