【问题标题】:How does creating two instances of Tk work with one mainloop?创建两个 Tk 实例如何与一个主循环一起工作?
【发布时间】:2025-12-10 07:25:01
【问题描述】:

如何将master = Tk()添加到tkinter.Frame子类的__init__
当只调用app.mainloop() 时产生两个窗口(@98​​7654323@ 和app2)?

from tkinter import Frame,Button,Tk

class Application(Frame):

    def say_hi(self):
        print('Hello world?!')

    def close(self):
        self.master.destroy()

    def createWidgets(self):
        self.quit_b = Button(self, width=12, text='Quit', bg='tan',
                    command=self.close)
        self.quit_b.grid(row=0, column=0, padx=8, pady=8)

        self.hello_b = Button(self, width=12, text='Hello',
                    command=self.say_hi)
        self.hello_b.grid(row=0, column=1, padx=8, pady=8)

    def __init__(self):
        master = Tk() # <------------------------ ! see here !
        Frame.__init__(self, master)
        self.grid()
        self.createWidgets()


app = Application()
app.master.title('Hello world!')

app2 = Application()
app2.master.title('Hello world! 2')

app.mainloop()

【问题讨论】:

    标签: python class tkinter


    【解决方案1】:

    您不能创建类Tk 的两个实例,并且在另一个类的__init__ 中实例化它有点不寻常。您的代码应该可以工作,但我从未见过这样做过。

    在创建任何其他小部件之前,您需要创建Tk 的实例。由于您的主应用程序是 Frame 的子类,因此您在初始化 Tkinter 之前部分地创建了 Frame 的实例,这根本不是应该完成的方式。它可能有效,但行为未定义。

    相反,通常最好将您的应用程序创建为 Tk 的子类:

    from Tkinter import tk
    class Application(tk.Tk):
        ...
    
    app = Application(...)
    app.mainloop()
    

    或者,在全局范围内创建Tk 的实例,并将其作为参数传递给您的其他小部件:

    from Tkinter import tk
    class Application(tkFrame):
        ...
    root = tk.Tk()
    myframe = Application(root)
    root.mainloop()
    

    如果您需要多个窗口,请使用 Toplevel 类创建其他窗口。

    【讨论】:

    • @HonestAbe:因为您在Application 的构造函数中创建了Tk 的实例,并创建了Application 的两个实例,所以您将获得两个Tkinter 实例。根本没有理由这样做,并且会产生意想不到的结果(显然,因为发生的事情不是您所期望的)。
    • 我稍微清理了这个问题,并删除了我在这个答案上的旧 cmets。您能否编辑此答案以澄清:“您不能创建 Tk 类的两个实例......”。你是说app2 中的master = Tk() 替换了app 中创建的那个吗?然后你能解释一下为什么 app.mainloop() 对两者都有效吗?谢谢!
    • @HonestAbe: mainloop 不创建任何窗口,它是一个简单的事件循环。每次调用Tk() 时,它都会创建一个窗口并初始化 tk 子系统。此初始化并非旨在为一个应用程序执行两次。
    • 这没什么大不了的,但是...事实证明,使用 tk 作为别名会阻止方法级别的代码完成(使用 PyScripter)。换句话说,如果我输入self.myEntry.,输入方法列表中不会出现任何框。也许这与TkBaseWidget 类具有self.tk 的事实有关。当我将别名更改为 tki 时,它解决了这个问题。再次感谢您在这里的所有帮助。
    最近更新 更多