2016-10-13 5 views
3

私はメインスレッド上で動作する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() 

答えて

2

私はあなたがコードをZE表示することはできませんが、あなたは特にカスタムイベントを発射、Tkinterののイベントシステムになっているはずですので、私はTkinterのとあまり慣れていないんです。

This questionは、あなたがあなたがQueueモジュールから、Queueを使用することができます

1

を始めるのに役立つことがあります。

def get_queue(self, queue): 
    status = queue.get() 
    if status: 
     self.do_your_action() 
    self.master.after(1000, self.get_queue) 

進捗バーのウィンドウでは、進行状況バーが終了したらキューを渡して何かを入れます。

関連する問題