线程在窗口被销毁之前不会停止,除非线程停止,否则窗口不会破坏



所以我有一个窗口,它由一个在后台运行的线程控制,并在必要时更改GUI,在某个时候,这个线程将被指示更改窗口(包括破坏它所在的窗口并启动另一个窗口(,但这永远不会发生,因为在窗口更改之前,线程不会停止执行。

下面是一个简化的例子:

class Window1:
def __init__(...):
self.Master = tk.Tk()
# some code
self.BackgroundUpdates = threading.Thread(target=self.ActiveWindow)
self.BackgroundUpdates.start()
def ActiveWindow(self):
# gets some instruction
if instruction == 'next window':
nextWindow(self)
def StartWindow(self):
self.Master.mainloop()
def KillWindow(self):
self.Master.destroy()

class Window2:
def __init__(...):
self.Master = tk.Tk()
# some code...
def StartWindow(self):
self.Master.mainloop()

def nextWindow(objectWindow):
objectWindow.KillWindow()
# when this function is called it never gets past the line above
nextWindow = Window2()
nextWindow.StartWindow()
application = Window1()
application.StartWindow()

有没有一种方法可以重新安排我处理线程的方式,这样我就不会遇到这个问题?

一个可运行的例子:

import tkinter as tk
import threading
class MainWindow:
def __init__(self):
self.Master = tk.Tk()
self.Frame = tk.Frame(self.Master, width=100, height=100)
self.Frame.pack()
self.Updates = threading.Thread(target=self.BackgroundUpdates)
self.Updates.start()
def BackgroundUpdates(self):
# imagine instructions to be a really long list with each element being a 
# different instruction
instructions = ['instruction1', 'instruction2', 'next window']
while True:
if instructions[0] == 'next window':
ChangeWindow(self)
else:
instructions.remove(instructions[0])
def StartWindow(self):
self.Master.mainloop()
def KillWindow(self):
self.Master.destroy()
class SecondaryWindow:
def __init__(self):
self.Master = tk.Tk()
self.Frame = tk.Frame(self.Master, width=100, height=100)
self.Frame.pack()
def StartWindow(self):
self.Master.mainloop()
def KillWindow(self):
self.Master.destroy()
def ChangeWindow(oldObject):
oldObject.KillWindow()
# the line above will halt the program, since it has to wait on the thread to 
# finish before the window can be destroyed, but this function is being called 
# from within the thread and so the thread will never stop executing
del oldObject
newObject = SecondaryWindow()
newObject.StartWindow()
window = MainWindow()
window.StartWindow() 

我意识到tkinter是单线程的,可以在这里进行更多解释:

https://stackoverflow.com/a/45803955/11702354

问题是,我试图从一个不同的线程破坏我的窗口,而不是在创建窗口的线程中。为了解决这个问题,我必须使用Tkinter模块中的"after"方法以及事件,这意味着我可以控制后台的东西(即,等待连接的服务器发出的特定命令(,当我需要更改窗口时,我会设置事件。

我修改后的部分代码如下所示:

def CheckEvent(self):
if LOBBY_EVENT.is_set():
ChangeWindow(self, 'game')
self.Master.after(5000, self.CheckEvent)
def StartWindow(self):
self.Master.after(5000, self.CheckEvent)
self.Master.after(2000, self.HandleInstruction)
self.Master.mainloop()

因此,每当我为我的窗口调用StartWindow方法时,它会每5秒检查一次事件是否已设置,然后每2秒转到一个单独的函数"HandleInstruction",它允许我在GUI中创建一个响应(我还使用队列将信息传递给该函数(

如果有人偶然发现它,我希望这能消除困惑!

最新更新