【发布时间】:2017-02-22 20:24:09
【问题描述】:
我有一个在主线程上运行的 tkinter 应用程序。在接收到用户的一些输入后,会创建一个新线程来执行单独类中的功能。主线程继续到 Toplevel 进度窗口。
我的问题是,当第二个线程完成其任务时,我如何与主线程通信以关闭进度窗口?
import tkinter as tk
from tkinter import ttk
from threading import Thread
import time
class Application:
def __init__(self, master):
# set main window
frame = tk.Frame(master, width=300, height=100)
frame.pack(fill=tk.BOTH)
# button widget
run_button = tk.Button(frame, text="GO", command=self.do_something)
run_button.pack()
# simulate some gui input from user
self.user_input = "specified by user"
def do_something(self):
thread1 = Thread(target=FunctionClass, args=(self.user_input,))
thread1.start() # launch thread
ProgressWindow() # main thread continues to new tkinter window
class ProgressWindow(tk.Toplevel):
""" displays progress """
def __init__(self):
super().__init__()
self.progress = ttk.Progressbar(
self, orient="horizontal", length=300, mode="indeterminate")
self.progress.pack()
self.note = "Processing data..."
self.p_label = tk.Label(self, text=self.note)
self.p_label.pack()
self.progress.start(50)
class FunctionClass:
""" thread1 works on this class """
def __init__(self, user_data):
self.user_data = user_data
self.do_something_else()
def do_something_else(self):
# simulate thread 1 working
time.sleep(3)
print("Thread1 job done")
if __name__ == "__main__":
root = tk.Tk()
Application(root)
root.mainloop()
* 更新 *
iCart 建议的 tkinter 的 event_generate 效果很好。请参阅下面的代码更新。
import tkinter as tk
from tkinter import ttk, messagebox
from threading import Thread
import time
class Application:
def __init__(self, master):
# set main window
frame = tk.Frame(master, width=300, height=100)
frame.pack(fill=tk.BOTH)
# button widget
run_button = tk.Button(frame, text="GO", command=self.do_something)
run_button.pack()
# simulate some gui input from user
self.user_input = "specified by user"
def do_something(self):
thread1 = Thread(target=FunctionClass, args=(self.user_input,))
thread1.start() # launch thread
ProgressWindow() # main thread continues to new tkinter window
class ProgressWindow(tk.Toplevel):
""" displays progress """
def __init__(self):
super().__init__()
self.progress = ttk.Progressbar(self, orient="horizontal", length=300, mode="indeterminate")
self.progress.pack()
self.note = "Processing data..."
self.p_label = tk.Label(self, text=self.note)
self.p_label.pack()
self.progress.start(50)
class FunctionClass:
""" thread1 works on this class """
def __init__(self, user_data):
self.user_data = user_data
self.do_something_else()
def do_something_else(self):
# simulate thread 1 working
time.sleep(3)
print("Thread1 job done")
# call <<stop>> virtual event (unsure if 'tail' is necessary here)
root.event_generate("<<stop>>", when="tail")
def end_program(*args):
""" called with tkinter event_generate command after thread completion """
messagebox.showinfo("Complete", "Processing Complete")
root.destroy()
if __name__ == "__main__":
root = tk.Tk()
Application(root)
root.bind("<<stop>>", end_program) # bind to event
root.mainloop()
【问题讨论】:
-
这能回答你的问题吗? Tkinter: invoke event in main loop
标签: python multithreading tkinter python-3.4