You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python tkinter自定义Toplevel类构造函数无副作用实现求助

问题分析与解决方案

你的代码出现两个顶层窗口的核心原因是重复创建Toplevel实例:在show_dialog方法中手动创建了一个Toplevel,随后实例化继承自Toplevel的Dialog类时,super().__init__(top)又会创建一个新的顶层窗口,最终导致两个窗口出现。

关键修改点

  1. 删除show_dialog中手动创建Toplevel的代码,直接实例化Dialog类,让Dialog自身作为顶层窗口。
  2. 调整Dialog的构造函数,将主窗口root作为父参数传入,同时在Dialog内部处理窗口位置和标题。
  3. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 09:22:40