Run thread from Tkinter and wait until it's finished
To prevent the GUI from freezing you need self.run()
to end quickly.It needs to spawn a thread, start the thread, then end:
import Queuesentinel = object()root = tkinter.Tk()...def run(self, url): outqueue = Queue.Queue() thr = threading.Thread(target=self.run_tests, args=(url, outqueue)) thr.start() root.after(250, self.update, outqueue)
Now the function this thread runs can run for a long time:
def run_tests(self, url, outqueue): outqueue.put("Running test #1...") self.webtester.urlopen(url) outqueue.put("Running test #2") self.webtester.test2() outqueue.put(sentinel)
But because Tkinter expects all GUI calls to originate from a single thread, this spawned thread must not make any GUI calls. For it to interact with the GUI, you can send output (such as a status update message) through a Queue.Queue
and concurrently let the main Tkinter thread monitor this Queue.Queue
periodically (through calls to root.after
):
def update(self, outqueue): try: msg = outqueue.get_nowait() if msg is not sentinel: self.appendLine(msg) root.after(250, self.update, outqueue) else: # By not calling root.after here, we allow update to # truly end pass except Queue.Empty: root.after(250, self.update, outqueue)