Python tkinter自定义Toplevel类构造函数无副作用实现求助
问题分析与解决方案
你的代码出现两个顶层窗口的核心原因是重复创建Toplevel实例:在show_dialog方法中手动创建了一个Toplevel,随后实例化继承自Toplevel的Dialog类时,super().__init__(top)又会创建一个新的顶层窗口,最终导致两个窗口出现。
关键修改点
- 删除
show_dialog中手动创建Toplevel的代码,直接实例化Dialog类,让Dialog自身作为顶层窗口。 - 调整
Dialog的构造函数,将主窗口root作为父参数传入,同时在Dialog内部处理窗口位置和标题。 - 修正
quit方法,销毁Dialog自身而非外部传入的窗口对象。
修正后的完整代码
from tkinter import * from tkinter import ttk class App(Frame): dialog = None def __init__(self, root): super(App, self).__init__(root) self.root = root self.create_widgets() def create_widgets(self): self.grid(row=3, column=1) self.t1 = Text(root, wrap="word") self.t1.grid(row=0, column=0, rowspan=2, sticky="nsew") self.b1 = Button(root, text=" Create ", command=self.show_dialog) self.b1.grid(row=2, column=0, pady=10) root.rowconfigure(0, weight=3) root.columnconfigure(0, weight=1) def show_dialog(self): # 直接实例化Dialog,无需提前创建Toplevel self.dialog = Dialog(self.t1, self.root) class Dialog(Toplevel): def __init__(self, t1, parent): # 调用父类构造,将主窗口作为父窗口传入 super().__init__(parent) self.t1 = t1 self.parent = parent self.title("Child") # 计算并设置窗口位置 self.update_idletasks() # 确保获取正确的窗口尺寸 x = self.parent.winfo_x() + self.parent.winfo_width()//2 - self.winfo_width()//2 y = self.parent.winfo_y() + self.parent.winfo_height()//2 - self.winfo_height()//2 self.geometry(f"100x75+{x}+{y}") self.widget() def widget(self): self.e1 = Entry(self) self.e1.grid(row=0, column=0) self.b1 = Button(self, text="Submit", command=self.on_submit) self.b1.grid(row=1, column=0, pady=15) def on_submit(self): self.t1.insert("insert", self.e1.get()) self.destroy() # 提交后直接销毁对话框 def quit(self): self.destroy() root = Tk() root.title("Parent") root.geometry("400x250+400+200") app = App(root) app.mainloop()
补充说明
super().__init__(parent)是正确的调用方式,它会以parent为父窗口创建一个新的Toplevel实例,也就是Dialog自身。- 添加
self.update_idletasks()是为了确保在计算窗口位置前,Toplevel已经完成初始化,能获取到正确的自身尺寸。 - 提交后直接调用
self.destroy()可以关闭对话框,无需额外维护外部窗口对象。
内容的提问来源于stack exchange,提问作者Chuck
相关产品推荐
相关产品推荐

