出于某种原因,mainloop() 没有结束。最后的 print 语句永远不会被触发,但其他一切都会触发。知道是什么原因造成的或如何解决它。即使没有线程也会发生。
import time
from tkinter.filedialog import askdirectory
from tkinter import *
def threading():
t1=Thread(target=checkProgress)
t1.start()
def checkProgress():
loading_window.geometry = ("500x500")
text = "The device is being reset. This will take a minute."
Label(loading_window, text=text, font=('times', 12)).pack()
loading_window.update()
time.sleep(3)
print("The connection is complete!")
Tk().withdraw()
download_location = askdirectory(title='Find and select the download folder', mustexist=TRUE)
loading_window = Tk()
loading_window.after(200, threading())
loading_window.mainloop()
print("Finished")
解决方案是在多线程时必须使用按钮。我想我尝试了一百万种不同的方法,出于某种原因,destroy() 只有在没有线程或使用按钮调用它时才能正常工作。我不知道为什么,但这很烦人。这是解决方案。主要部分是带有 destroy 命令的按钮。非常令人沮丧,我不能在函数完成休眠后简单地调用命令。我必须通过按钮调用它。
def threading():
t1=Thread(target=work)
t1.start()
def work():
print("sleep time start")
time.sleep(5)
print("sleep time stop")
Label(loading_window, text="The device is ready! Please click next.", font=('times', 12)).pack()
Button(loading_window,text="Next",command = destroy).pack()
def destroy():
loading_window.destroy()
loading_window = Tk()
loading_window.geometry = ("500x500")
Label(loading_window, text="The device is being reset. This will take a minute.", font=('times', 12)).pack()
threading()
loading_window.mainloop()
因为有两个
Tk()
的实例:
Tk().withdraw()
(隐藏实例)loading_window = Tk()
即使你关闭了第二个实例,
mainloop()
仍然会运行,因为有一个隐藏的Tk()
实例。
你应该只使用一个
Tk()
的实例:
import time
from threading import Thread
from tkinter.filedialog import askdirectory
from tkinter import *
def threading():
t1=Thread(target=checkProgress)
t1.start()
def checkProgress():
loading_window.geometry("500x500")
text = "The device is being reset. This will take a minute."
Label(loading_window, text=text, font=('times', 12)).pack()
loading_window.update()
loading_window.deiconify() # show the window
time.sleep(3)
print("The connection is complete!")
loading_window.destroy() # destroy the window
# only create one instance of Tk()
loading_window = Tk()
loading_window.withdraw() # hide the window
download_location = askdirectory(title='Find and select the download folder', mustexist=TRUE)
loading_window.after(200, threading)
loading_window.mainloop()
print("Finished")
注意,大多数人说不建议直接在子线程中更新 tkinter widgets,因为 tkinter 不是线程安全的。
下面是修改后的代码,以尽量减少线程中的直接更新 tkinter 小部件:
import time
from threading import Thread
from tkinter.filedialog import askdirectory
from tkinter import *
def threading():
loading_window.deiconify() # show the window
t1=Thread(target=checkProgress)
t1.start()
def checkProgress():
time.sleep(3)
print("The connection is complete!")
loading_window.after(10, loading_window.destroy) # destroy the window
loading_window = Tk()
loading_window.geometry("500x500")
text = "The device is being reset. This will take a minute."
Label(loading_window, text=text, font=('times', 12)).pack()
loading_window.withdraw() # hide the window
download_location = askdirectory(title='Find and select the download folder', mustexist=TRUE)
loading_window.after(200, threading)
loading_window.mainloop()
print("Finished")
你需要一些东西来破坏窗口以退出主循环。 您可以添加一个按钮来关闭窗口,或者如下所示添加一行以在完成后销毁窗口:
import tkinter as tk
from tkinter import filedialog
import time
from threading import Thread
def threading():
t1=Thread(target=checkProgress)
t1.start()
def checkProgress():
loading_window.geometry = ("500x500")
text = "The device is being reset. This will take a minute."
tk.Label(loading_window, text=text, font=('times', 12)).pack()
loading_window.update()
time.sleep(3)
# destroy the window
loading_window.destroy()
print("The connection is complete!")
if __name__=="__main__" :
# tk().withdraw()
download_location = filedialog.askdirectory(title='Find and select the download folder', mustexist=tk.TRUE)
loading_window = tk.Tk()
loading_window.after(200, threading)
loading_window.mainloop()
print("Finished")
更新:我建议使用
Event
并在windows cmd脚本中添加daemon=True
:
import time
import tkinter as tk
from threading import Thread, Event
def threading(event):
try:
t1=Thread(target=checkProgress, daemon=True)
t1.start()
except:
print("Take the error management here ..")
finally:
print("Thread is running")
def checkProgress():
root.geometry = ("500x500")
text = "The device is being reset. This will take a minute."
tk.Label(root, text=text, font=('times', 12)).pack()
root.update()
time.sleep(3)
print("The connection is complete!")
print("Finished")
root.destroy()
if __name__=="__main__" :
root = tk.Tk()
event = Event()
root.after(200, threading(event))
event.set()
root.mainloop()