[PYTHON] Lorsque tkinter est démarré dans un autre thread, arrêtez le traitement par ce thread lui-même, nettoyez les variables, puis arrêtez le thread.

Quand j'ai démarré tkinter dans un autre thread, j'ai eu du mal à terminer le programme normalement, donc je partagerai les informations.

tkinter boucle le dessin et le traitement des événements en appelant mainloop (). Vous pouvez terminer mainloop () en appelant destroy () dans tkinter. Après cela, lorsque le thread se termine, tkinter est également détruit.

Cependant, si destroy () était appelé depuis un autre thread ou si le widget tkinter (partie GUI) était toujours assigné à la variable d'instance, le programme ne pouvait pas se terminer normalement.

Je vais expliquer avec un exemple de programme.

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 () crée une interface graphique et un sous-thread, et le sous-thread démarre gui.start ().

Lors de la fin du processus main (), appelez gui.quit () pour définir l'indicateur de fin, le sous-thread vérifie toutes les 1 seconde et le sous-thread lui-même appelle destroy (). Je le fais. L'appel de gui.window.destroy () directement au lieu de ce gui.quit () a provoqué une boucle infinie. Je ne pouvais pas entendre CTRL + C, et je n'avais pas d'autre choix que de forcer l'arrêt (vidage de mémoire) avec CTRL + \.

Dans le sous-thread, après avoir quitté mainloop (), la variable d'instance est del. Si ce traitement «del» n'est pas effectué, le programme peut se terminer anormalement (vidage de mémoire) ou générer un message d'erreur sans fin.

Expérimentez ce qui se passe en faisant gui.window.destroy () directement depuis main () ou en commentant le traitement del de la variable d'instance.

Soyez prudent lorsque vous utilisez tkinter et threads ensemble.

Recommended Posts

Lorsque tkinter est démarré dans un autre thread, arrêtez le traitement par ce thread lui-même, nettoyez les variables, puis arrêtez le thread.
Rechercher le nom et les données d'une variable libre dans un objet fonction