Tkinter中winfo_height()始终返回1的问题求助
解决CTkFrame调用winfo_height()始终返回1的问题
问题场景
点击expand_keyword按钮触发函数,生成多个single_cve_frame(CTkFrame组件)并通过pack()布局到父容器中,需要获取这些框架的实际高度,但调用winfo_height()始终返回1。试过在pack()后调用update_idletasks(),甚至静态设置框架高度,结果还是一样。
用户代码示例:
def expand_keyword(self, frame: ExpandableKeywordCVEsFrame, organized_cves): for cve in organized_cves[keyword]['matching_cves']: single_cve_frame = ctk.CTkFrame(frame, fg_color = '#E1E1E1') ctk.CTkLabel(single_cve_frame, text = cve, text_color = 'black', font = ('Inter', 18) ).place(relx = 0.2, rely = 0.5, relwidth = 0.25, relheight = 1, anchor = 'center') single_cve_frame.pack(expand = True, fill = 'both') print(single_cve_frame.winfo_height()) self.master.update_idletasks() print(single_cve_frame.winfo_height())
原因分析
place()布局不触发父容器尺寸计算:内部的CTkLabel用place()定位,这种布局方式不会向父框架(single_cve_frame)请求空间,导致父框架的自然最小尺寸为1x1。- CTkFrame的尺寸依赖布局状态:CustomTkinter的组件尺寸需要等布局完全渲染后才会确定,即使调用
update_idletasks(),如果没有子组件撑大框架,还是会保持最小尺寸。
解决办法
方法1:改用pack()/grid()布局子组件
把内部的CTkLabel换成pack()布局,让父框架自动根据子组件尺寸调整自身大小,之后就能获取正确高度:
def expand_keyword(self, frame: ExpandableKeywordCVEsFrame, organized_cves): for cve in organized_cves[keyword]['matching_cves']: single_cve_frame = ctk.CTkFrame(frame, fg_color='#E1E1E1') # 用pack()替代place()布局Label ctk.CTkLabel(single_cve_frame, text=cve, text_color='black', font=('Inter', 18) ).pack(expand=True, fill='both', padx=10, pady=5) single_cve_frame.pack(expand=True, fill='both', pady=2) # 调用update()强制刷新布局 self.master.update() print(single_cve_frame.winfo_height())
方法2:手动设置框架高度并强制刷新
如果必须用place()布局,直接给CTkFrame设置固定高度,再调用update()触发尺寸生效:
def expand_keyword(self, frame: ExpandableKeywordCVEsFrame, organized_cves): for cve in organized_cves[keyword]['matching_cves']: # 手动指定框架高度 single_cve_frame = ctk.CTkFrame(frame, fg_color='#E1E1E1', height=40) ctk.CTkLabel(single_cve_frame, text=cve, text_color='black', font=('Inter', 18) ).place(relx=0.2, rely=0.5, relwidth=0.25, relheight=1, anchor='center') single_cve_frame.pack(expand=True, fill='both') # 强制更新所有组件布局 self.master.update() print(single_cve_frame.winfo_height())
方法3:绑定<Configure>事件获取真实尺寸
组件最终尺寸可能在布局完成后才确定,给CTkFrame绑定配置事件,当尺寸变化时自动获取:
def on_frame_configure(self, event): # event.widget就是当前的single_cve_frame print(f"框架实际高度:{event.widget.winfo_height()}") def expand_keyword(self, frame: ExpandableKeywordCVEsFrame, organized_cves): for cve in organized_cves[keyword]['matching_cves']: single_cve_frame = ctk.CTkFrame(frame, fg_color='#E1E1E1') ctk.CTkLabel(single_cve_frame, text=cve, text_color='black', font=('Inter', 18) ).place(relx=0.2, rely=0.5, relwidth=0.25, relheight=1, anchor='center') # 绑定尺寸变化事件 single_cve_frame.bind("<Configure>", self.on_frame_configure) single_cve_frame.pack(expand=True, fill='both')
内容的提问来源于stack exchange,提问作者Rodolfo
相关产品推荐
相关产品推荐

