Kivy如何在__init__方法执行后调用函数以正确定位生成的Label组件
问题核心原因
__init__执行阶段控件尚未完成布局渲染,self.height取到的是初始默认值100,并非实际窗口渲染后的高度。你提到的延迟调用Label创建逻辑的思路是可行的,Kivy常用两种实现方案:
方案1:使用Clock.schedule_once延迟执行
该方案会在下一帧界面渲染完成后调用Label创建方法,此时控件尺寸已经更新为实际值:
from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.metrics import dp from kivy.clock import Clock class LabelsWindow(BoxLayout): labels_list = ['A', 'B', 'C'] def __init__(self, **kwargs): super().__init__(**kwargs) # 延迟1帧调用创建方法,0代表下一帧立即执行 Clock.schedule_once(self.create_labels, 0) def create_labels(self, dt): label_height = dp(50) for i, e in enumerate(self.labels_list): label = Label( text=e, size_hint=(1, None), height=label_height, pos_hint={'x':0, 'top':1 - (label_height/self.height)*i} ) self.add_widget(label)
方案2:绑定on_size事件适配窗口缩放
该方案不仅初始化时能正确生成Label,窗口大小变化时也会自动刷新Label位置,适配动态缩放场景:
from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.metrics import dp class LabelsWindow(BoxLayout): labels_list = ['A', 'B', 'C'] def __init__(self, **kwargs): super().__init__(**kwargs) # 绑定尺寸变化事件,尺寸更新时自动触发刷新 self.bind(size=self.refresh_labels) def refresh_labels(self, instance, new_size): # 清空原有控件避免重复添加 self.clear_widgets() label_height = dp(50) for i, e in enumerate(self.labels_list): label = Label( text=e, size_hint=(1, None), height=label_height, pos_hint={'x':0, 'top':1 - (label_height/new_size[1])*i} ) self.add_widget(label)
原代码的两处语法疏漏
size_hint的第二个参数是高度占父控件的比例,不能直接传dp值;固定高度需要把size_hint_y设为None,再给height属性赋值固定值self.add_widget未加括号传入label对象,实际运行不会添加控件
内容的提问来源于stack exchange,提问作者user14122287
相关产品推荐
相关产品推荐

