[PYTHON] [Tkinter] Améliorez la réactivité de l'interface graphique

1.Tout d'abord

Aujourd'hui, je vais vous expliquer comment utiliser Threading pour améliorer sa réactivité lors de la création d'une application GUI.

2. Ce que vous voulez faire

Concevez un écran GUI simple comme indiqué dans la figure ci-dessous. Lorsque le bouton du haut est cliqué, il est affiché dans l'ordre de 0 à 9 en bas. image.png Écrivons tout de suite le code dans Tkinter.

3. Code qui ne répond pas

Tout d'abord, j'ai écrit le code suivant. Lorsque le bouton est enfoncé, _main_func () est exécuté. _main_func () est une fonction qui affiche de 0 à 9 à l'aide de l'instruction For.

Deux types d'étiquettes Tkinter et d'instructions d'impression ont été utilisés pour afficher les résultats.

3.1. Code de programmation (1)

tkinter_wo_threading.py


import tkinter as tk
from tkinter import ttk
from tkinter import font
import time

class Application(tk.Frame):
    def __init__(self,master):
        super().__init__(master)
        self.pack()
        self.master.geometry("300x300")
        self.master.title("Tkinter Freezes after clicking Buttons")


        self.font_lbl_big = font.Font( family="Meiryo UI", size=30, weight="bold" )
        self.font_lbl_middle = font.Font( family="Meiryo UI", size=15, weight="bold" )
        self.font_lbl_small = font.Font( family="Meiryo UI", size=12, weight="normal" )

        self.create_widgets()

    def create_widgets(self):

        # Frame
        self.main_frame = tk.LabelFrame(self.master, text ='', font = self.font_lbl_small)
        self.main_frame.place(x=25,y=25)
        self.main_frame.configure(height = 250, width=250)
        self.main_frame.grid_propagate(0)
        self.main_frame.grid_columnconfigure(0, weight = 1)
       
        # Start Button
        self.btn_Start = ttk.Button( self.main_frame)
        self.btn_Start.configure( text='Start' )
        self.btn_Start.configure( command=self._main_func)
        self.btn_Start.grid( column=0, row=0,  pady=10 , sticky='NESW')

        # Label Title
        self.lbl_title = ttk.Label( self.main_frame)
        self.lbl_title.configure( text='Calculation Results Shown Here' )
        self.lbl_title.grid( column=0, row=1,  padx = 20, pady=20 ,sticky='EW')

        # Label Result
        self.lbl_result = ttk.Label( self.main_frame )
        self.lbl_result.configure( text='' )
        self.lbl_result.grid( column=0, row=2,  padx = 100, pady=10 ,sticky='EW')


    def _main_func(self):

        for i in range(10):
            print(i)
            self.lbl_result.configure(text = i, font = self.font_lbl_big)
            time.sleep(0.1)


def main():
    root = tk.Tk()
    app = Application(master=root)#Inherit
    app.mainloop()

if __name__ == "__main__":
    main()

3.2. Résultat de l'exécution

Exécutons ce code. Si vous appuyez sur le bouton, le programme cessera de répondre jusqu'à ce que la boucle d'instruction for se termine. L'instruction d'impression imprime les résultats en continu, mais l'interface graphique reste stationnaire. Et lorsque la boucle de l'instruction for se termine, seul le dernier nombre est affiché. Ce n'est pas ce à quoi vous vous attendiez au début.

C'est parce que Python exécute le code ligne par ligne. Si cela reste tel quel, la réponse sera médiocre car les autres événements ne peuvent même pas démarrer jusqu'à ce qu'un événement soit traité par le programme GUI. with_thread.gif

4. Code qui utilise Threading pour améliorer la réactivité

À ce stade, le filetage est utilisé. Pour le contenu lié au filetage, reportez-vous au matériel de référence.

4.1. Code de programmation avec une meilleure réactivité (1)

Tout d'abord, nous allons introduire le filetage.

import threading

À son tour, changez la fonction de rappel du bouton en _start_thread (). Dans ce _start_thread (), placez la fonction pour démarrer _main_func () en tant que thread. C'est une image que vous pouvez spécifier comme cible et écrire un début.


def _start_thread(self):
        self.thread_main = threading.Thread(target = self._main_func)
        self.thread_main.start()

L'ensemble du code.

tkinter_with_threading.py


import tkinter as tk
from tkinter import ttk
from tkinter import font
import time
import threading

class Application(tk.Frame):
    def __init__(self,master):
        super().__init__(master)
        self.pack()
        self.master.geometry("300x300")
        self.master.title("Tkinter Freezes after clicking Buttons")


        self.font_lbl_big = font.Font( family="Meiryo UI", size=30, weight="bold" )
        self.font_lbl_middle = font.Font( family="Meiryo UI", size=15, weight="bold" )
        self.font_lbl_small = font.Font( family="Meiryo UI", size=12, weight="normal" )

        self.create_widgets()

    def create_widgets(self):

        # Frame
        self.main_frame = tk.LabelFrame(self.master, text ='', font = self.font_lbl_small)
        self.main_frame.place(x=25,y=25)
        self.main_frame.configure(height = 250, width=250)
        self.main_frame.grid_propagate(0)
        self.main_frame.grid_columnconfigure(0, weight = 1)

       
        # Start Button
        self.btn_Start = ttk.Button( self.main_frame)
        self.btn_Start.configure( text='Start' )
        self.btn_Start.configure( command=self._start_thread)
        self.btn_Start.grid( column=0, row=0,  pady=10 , sticky='NESW')

        # Label Title
        self.lbl_title = ttk.Label( self.main_frame)
        self.lbl_title.configure( text='Calculation Results Shown Here' )
        self.lbl_title.grid( column=0, row=1,  padx = 20, pady=20 ,sticky='EW')

        # Label Result
        self.lbl_result = ttk.Label( self.main_frame )
        self.lbl_result.configure( text='' )
        self.lbl_result.grid( column=0, row=2,  padx = 100, pady=10 ,sticky='EW')


    #-----------------------------------------------------------
    # Start Thread
    # -----------------------------------------------------------
    def _start_thread(self):
        self.thread_main = threading.Thread(target = self._main_func)
        self.thread_main.start()

    def _main_func(self):

        for i in range(10):
            print(i)
            self.lbl_result.configure(text = i, font = self.font_lbl_big)
            time.sleep(0.1)


def main():
    root = tk.Tk()
    app = Application(master=root)#Inherit
    app.mainloop()

if __name__ == "__main__":
    main()

4.2. Résultat de l'exécution

C'est le résultat de l'exécution de code à l'aide de Threading. without_thread.gif

J'ai pu confirmer que le programme fonctionne comme prévu à l'origine. Le programme est plus réactif et peut gérer d'autres événements.

Résumé

J'ai pu améliorer la réactivité du programme GUI en utilisant des threads.

Matériel de référence

1.python#Threading 2. Compréhension complète du thread Python et du multitraitement 3. Implémenter dans le thread [Python]

Recommended Posts

[Tkinter] Améliorez la réactivité de l'interface graphique
Application GUI facile avec Tkinter Text
Création d'interface graphique en python avec tkinter 2
À propos de la création de l'interface graphique à l'aide de TKinter de Python
Rendez les applications GUI super faciles avec tkinter
Créer une application graphique avec Tkinter de Python