[PYTHON] When tkinter is started in another thread, the thread itself should stop and clean up the variables before terminating the thread.

When I started tkinter in another thread, I had a hard time terminating the program normally, so I will share the information.

tkinter loops drawing and event processing by calling mainloop (). You can terminate mainloop () by calling destroy () on tkinter. After that, when the thread ends, tkinter is also destroyed.

However, if you called destroy () from another thread, or if the tkinter widget (GUI part) was still assigned to the instance variable, the program could not be terminated normally.

I will explain with a sample program.

import time
import threading
import tkinter as tk


class GUI:

    def start(self):
        self.running = True
        self.window = tk.Tk()
        self.window.title("Sample")
        self.window.geometry('320x240')

        self.value = tk.StringVar()
        entry = tk.Entry(textvariable=self.value)
        entry.pack()

        self.window.after(1000, self._check_to_quit)
        self.window.mainloop()
        # need to delete variables that reference tkinter objects in the thread
        del self.value
        del self.window

    def _check_to_quit(self):
        if self.running:
            self.window.after(1000, self._check_to_quit)
        else:
            self.window.destroy()

    def quit(self):
        self.running = False


def main():
    gui = GUI()
    thread = threading.Thread(target=gui.start)
    thread.start()

    time.sleep(2)
    for i in 1, 2, 3, 'Dar!!':
        gui.value.set(i)
        time.sleep(1)

    gui.quit()
    thread.join()

if __name__ == '__main__':
    main()

main () creates a gui and a subthread, and the subthread starts gui.start ().

When terminating the main () process, call gui.quit () to set the end flag so that the subthread checks every 1 second and the subthread itself calls destroy (). I am doing it. Calling gui.window.destroy () directly instead of this gui.quit () caused an infinite loop. I couldn't even hear CTRL + C, and I had no choice but to force termination (core dump) withCTRL + \.

In the subthread, after exiting mainloop (), the instance variable is del. If this del processing is not performed, the program may terminate abnormally (core dump) or continue to output error messages endlessly.

Experiment with what happens by doing gui.window.destroy () directly from main () or commenting out the del processing of instance variables.

Be careful when using tkinter and threads together.

Recommended Posts

When tkinter is started in another thread, the thread itself should stop and clean up the variables before terminating the thread.
Look up the names and data of free variables in function objects