私はメインスレッド上で動作するtkinterアプリケーションを持っています。ユーザーから何らかの入力を受けた後、別のクラスで機能を実行するための新しいスレッドが作成されます。メインスレッドはToplevel進捗ウィンドウに進みます。tkinterアプリケーションからのマルチスレッド化
私の質問は、進行状況ウィンドウを閉じるために、2番目のスレッドがタスクを完了したときにメインスレッドとどのように通信できますか?
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()
* UPDATE *
の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()