【问题标题】:How to create new Tkinter window after mainloop()?如何在 mainloop() 之后创建新的 Tkinter 窗口?
【发布时间】:2013-01-15 11:11:45
【问题描述】:

我想在我的屏幕上动态创建 Tkinter 窗口。我知道我应该只有一个 mainloop()。我使用threading模块让mainloop在一个单独的线程中执行,所以它不会阻塞脚本。

执行 mainloop 后如何创建更多 Tkinter 窗口?

请看我的代码:

from Tkinter import *
import threading
import time

class box:
    def __init__(self, pos):
        self.master = Tk()
        self.master.geometry(pos) 
        self.canvas = Canvas(self.master, width=50, height=50, highlightthickness=0 )
        self.canvas.pack()
        self.rect = self.canvas.create_rectangle(0, 0, 50, 50, fill="red", outline="red")
        self.text = self.canvas.create_text(25, 24, text="99",fill="white", font=("calibri", 24, "bold"))

    def changeFill(self, color):
        self.canvas.itemconfig(self.rect, fill=color, outline=color) # change color

class box_manager(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.boxes = {}
        self.add_box(1, "50x50+300+300")
        self.add_box(2, "50x50+100+100")
    def add_box(self, num, pos):
        self.boxes[num] = box(pos)
    def run(self):
        mainloop()

tk = box_manager()
tk.start()

# How do I dynamically add new tkinter windows? the line below makes python.exe crash.
tk.add_box(3, "50x50+200+200")

Joel 评论后更新,还是不行:

from Tkinter import *
import threading
import time

class MyCustomWindow(Toplevel):
    def __init__(self):
        Toplevel.__init__(self)
        #setup goes here
        self.geometry("50x50+100+100") 
        self.canvas = Canvas(self, width=50, height=50, highlightthickness=0 )
        self.canvas.pack()

class App(Tk):

    def CreateFirst(self):
        self.anotherWindow = MyCustomWindow()
    def CreateSecond(self):
        self.secondWindow = MyCustomWindow()


class SecondWindow(threading.Thread):
    #after 2 seconds create a second window, python.exe crashes
    def run(self):
        time.sleep(2)
        tk.CreateSecond()

SecondWindow().start()
tk = App()
tk.CreateFirst()
mainloop()  

【问题讨论】:

  • 您确定需要线程吗?你可以在一个线程中使用 Tkinter 做很多事情。

标签: python tkinter


【解决方案1】:

执行 mainloop 后如何创建更多 Tkinter 窗口?

你没有。这不是 Tkinter 设计的工作方式。您应该始终只从主线程调用一次 mainloop。

【讨论】:

  • 好的,但是我将如何动态创建新的小部件?我在一个单独的线程中有一个循环,它监视打开的程序,应该为它看到的每个新程序创建一个新的对话框/小部件,就像某种覆盖一样。
  • @koen:您不能直接从单独的线程创建小部件。您必须将信息放入线程安全队列中,然后让您的主 GUI 线程轮询队列并创建小部件。
  • 太好了,这很有意义。我要试一试。
【解决方案2】:

附加(非根)窗口只是Toplevel 小部件。您只需将Toplevel 子类化,然后在您的主类中调用它:

class MyCustomWindow(tkinter.Toplevel):
    def __init__(self):
        tkinter.Toplevel.__init__(self)
        #setup goes here


class App(tkinter.Tk):

    def someCallback(self):
        self.anotherWindow = MyCustomWindow()

编辑

你没有子类Toplevel 当然,你可以直接使用它。

【讨论】:

  • 感谢您的帮助。我尝试了您的示例,但是当我在运行 mainloop 后在单独的线程中运行 MyCustomWindow 时,Python 崩溃了。假设我想显示一个窗口,等待 5 秒钟,然后同时显示另一个窗口。我该怎么做?
  • 嗯,首先,你有多个“根”或“主人”。任何给定的 tkinter 应用程序都应该只有一个 Tk() 实例。其他一切都应该是那个 one 实例的子节点。
  • 乔尔,你能看看我在原帖中的新代码吗?我试图理解你的解释。
  • 我已经能够修复它。 Mainloop 现在在主线程中运行。主线程从 python 队列中读取。我有一个单独的线程,可以将作业(新的顶级窗口)添加到队列中。感谢您的帮助。
  • 另见上面布莱恩的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
相关资源
最近更新 更多