0

python3.5

i need a GUI and a thread to handle heavy computation. the thread output some state info depend on computation result. Now i try the below code seems work fine. but when i press close(x) button of the window, the gui freezes.

import tkinter as tk
import threading
import time
import tkinter.scrolledtext as scrolledtext

class GUI:
    def __init__(self, master):
        self.master = master
        self.scrolledtext = scrolledtext.ScrolledText()
        self.scrolledtext['font'] = ('consolas', '12')
        self.scrolledtext.pack(expand=True, fill='both')
        self.scrolledtext.insert(tk.END, "test\n")
        self.master.protocol("WM_DELETE_WINDOW", self.closeme)

        self.threadTask = ThreadedTask(self.scrolledtext)
        self.threadTask.start()

    def closeme(self):
        self.threadTask.stop()
        self.threadTask.join()
        self.master.destroy()

class ThreadedTask(threading.Thread):
    def __init__(self,scrolledtext):
        threading.Thread.__init__(self)
        self.scrolledtext = scrolledtext
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def run(self):
        while(not self._stop_event.is_set()):
            time.sleep(1)
            # to do: something heavy computation....
            self.scrolledtext.insert(tk.END, "123\n")
            self._stop_event.wait(1)


root = tk.Tk()
root.title("Test")
main_ui = GUI(root)
root.mainloop()
Community
  • 1
  • 1
Shawn Lee
  • 1
  • 2
  • Instead of creating a new thread. Just use the `after` method ([example](https://ideone.com/iVtpke)). Takes the whole issue away. It's also not recommended to call widget methods from other threads. – Paul Rooney Mar 14 '19 at 10:45
  • [Edit] your Question and explain in detail **why** do you use `self._stop_event.wait(1)`? – stovfl Mar 14 '19 at 12:39
  • @ Paul Rooney , i need to use a thread to do something heavy. what's your recommended way to communicate between widget and thread. like this case, the thread have to output some info in GUI text, thanks. – Shawn Lee Mar 14 '19 at 13:22
  • @ stovfl , i need a GUI and a thread to handle heavy computation. the thread output some state info depend on computation result. Now i try the above code seems work fine. but when i press button of the window, the gui freezes. self._stop_event.wait(1) reference :https://stackoverflow.com/questions/5019436/python-how-to-terminate-a-blocking-thread/5205180#5205180. Thanks. – Shawn Lee Mar 14 '19 at 13:33
  • There is no button created in your `GUI` class, so how can you _press button of the window_? Also you better remove `time.sleep(1)` as `self._stop_event.wait(1)` is doing the same job. – acw1668 Mar 15 '19 at 01:34

1 Answers1

0

I've change the close function. Try now, on my debian it works.

 def closeme(self):

        if self.threadTask.is_alive():
            self.scrolledtext.insert(tk.END, "I', stopping\npress close again")
            self.threadTask.stop()
            #self.threadTask.join()
        else:
            self.master.destroy()
1966bc
  • 1,148
  • 1
  • 6
  • 11