Aujourd'hui, je vais vous expliquer comment utiliser Threading pour améliorer sa réactivité lors de la création d'une application GUI.
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. Écrivons tout de suite le code dans Tkinter.
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.
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()
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.
À ce stade, le filetage est utilisé. Pour le contenu lié au filetage, reportez-vous au matériel de référence.
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()
C'est le résultat de l'exécution de code à l'aide de Threading.
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.
J'ai pu améliorer la réactivité du programme GUI en utilisant des threads.
1.python#Threading 2. Compréhension complète du thread Python et du multitraitement 3. Implémenter dans le thread [Python]
Recommended Posts