Tkinter Frame组件父子绑定异常问题:子类B实例未显示在父类A容器内
问题分析与解决方案
我一眼就瞅出问题所在啦——你的Frm_btn类在初始化父类tk.Frame的时候,没有把传入的parent参数传递给父类构造器!这直接导致了组件层级混乱。
核心错误原因
当你创建Frm_btn(self)时,确实把Frm_tool的实例作为parent传了进去,但在Frm_btn的__init__方法里:
tk.Frame.__init__(self, width=24, height=24, bg="green")
这里只指定了尺寸和背景色,却没有把parent传给tk.Frame的构造函数。Tkinter的组件如果初始化时没指定父组件,会默认把根窗口(win)作为父组件,所以你的绿色按钮框才会跑到蓝色工具框的外面。
而你打印self.frm_btn得到.!frm_btn,这只能说明组件实例被成功创建了,但它的父组件并不是你期望的Frm_tool。
修正步骤
1. 修复Frm_btn的父类初始化
把传入的parent参数添加到tk.Frame的构造调用中:
class Frm_btn(tk.Frame): def __init__(self, parent): # 这里要把parent传递给父类Frame tk.Frame.__init__(self, parent, width=24, height=24, bg="green") self.parent = parent
或者更推荐使用super()来调用父类构造(更符合Python面向对象规范):
class Frm_btn(tk.Frame): def __init__(self, parent): super().__init__(parent, width=24, height=24, bg="green") self.parent = parent
2. 优化Frm_tool的初始化(可选但推荐)
你的Frm_tool类现在硬编码了self.parent=win,这会让组件耦合度太高,最好也让它接收parent参数:
class Frm_tool(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent, width=48, height=48, bg="blue") self.parent = parent # 创建Frm_btn实例,父组件是self(当前Frm_tool实例) self.frm_btn = Frm_btn(self) self.frm_btn.pack()
然后创建Frm_tool实例时传入根窗口:
frm_tool = Frm_tool(win)
完整修正后的代码
import tkinter as tk # class B class Frm_btn(tk.Frame): def __init__(self, parent): super().__init__(parent, width=24, height=24, bg="green") self.parent = parent # class A class Frm_tool(tk.Frame): def __init__(self, parent): super().__init__(parent, width=48, height=48, bg="blue") self.parent = parent # instance of class B self.frm_btn = Frm_btn(self) self.frm_btn.pack() print(self) # 返回 ".!frm_tool" print(self.frm_btn) # 返回 ".!frm_tool.!frm_btn" (注意这里的标识多了父组件前缀,说明层级正确) win = tk.Tk() win.configure(bg="red") # instance of class A frm_tool = Frm_tool(win) frm_tool.pack() win.mainloop()
现在运行代码,你会看到绿色的小框(Frm_btn)正确显示在蓝色的Frm_tool框内部,蓝色框又在红色的根窗口里,完全符合你的预期。另外注意打印self.frm_btn的结果变成了.!frm_tool.!frm_btn,这也证明它的父组件确实是Frm_tool了。
内容的提问来源于stack exchange,提问作者Leer
相关产品推荐
相关产品推荐

