Предисловие
Tkinter (интерфейс Tk) — это модуль стандартного набора инструментов Python Tk GUI. Tk и Tkinter работают на большинстве платформ Unix, но также могут использоваться в системах Windows и Macintosh. последующие версии Tk8.0 могут использоваться для реализации собственных оконных стилей и хорошо работают на большинстве платформ. Python использует Tkinter для быстрого создания приложений с графическим интерфейсом. Поскольку Tkinter встроен в установщик Python, вы можете импортировать библиотеку Tkinter после установки Python, а поскольку IDLE написан на Tkinter, Tkinter может работать с простыми графическими интерфейсами.
I. Описание проблемы
Если при запуске программы Python с графическим интерфейсом пользователя нажать кнопку для запуска требующей много времени операции, интерфейс зависнет и покажет, что он не отвечает, что сделает невозможным работу с другими компонентами.
II. идея решения
Используйте поток для выполнения функции события кнопки привязки, чтобы реализовать работу без задержек и устранить застревание интерфейса.
III. Пример кода
1. Поточный метод выполнения функции события кнопки привязки
import threading def thread_it(func, *args): """ Packing functions into threads """ self.myThread = threading.Thread(target=func, args=args) self.myThread.setDaemon(True) # When the main thread exits, the sub-threads exit directly after it, regardless of whether they finish running or not. self.myThread.start()
2. Полный код
import sys import time import tkinter as tk from tkinter.messagebox import askyesno from tkinter.scrolledtext import ScrolledText import threading class TestGui(object): def __init__(self, init_window_name): self.init_window_name = init_window_name self.init_window_name.title("Packing the button method into a thread to run a non-lagging test") # Setting the window title self.init_window_name.geometry('700x350') # Setting the window size """ Click on the upper right corner to close the form popup event """ self.init_window_name.protocol('WM_DELETE_WINDOW', lambda: self.thread_it(self.clos_window)) """ Component Container Creation""" self.log_frame = tk.Frame(self.init_window_name) # Creating a Container to Hold Logging Components self.log_frame.grid(padx=20, pady=0, row=1, column=0, sticky=tk.W) self.runs_button_frame = tk.Frame(self.init_window_name) # Creating a Container to Hold Logging Components self.runs_button_frame.grid(padx=20, pady=0, row=2, column=0, sticky=tk.W) """ logframe """ self.run_log = ScrolledText(self.log_frame, font=('SimHei', 13), width=69, height=17) self.run_log.grid(padx=20, pady=5, row=0, column=0) """ operate buttons """ self.start_run1 = tk.Button(self.runs_button_frame, text='begin print 1', font=('SimHei', 15, 'bold'), fg="white", bg="#1E90FF", width=25, command=lambda: self.thread_it(self.print1)) self.start_run1.grid(padx=20, pady=0, row=0, column=1) self.start_run2 = tk.Button(self.runs_button_frame, text='begin print 2', font=('SimHei', 15, 'bold'), fg="white", bg="#1E90FF", width=25, command=lambda: self.thread_it(self.print2)) self.start_run2.grid(padx=35, pady=0, row=0, column=2) def thread_it(self, func, *args): """ Packing functions into threads """ self.myThread = threading.Thread(target=func, args=args) self.myThread .setDaemon(True) # When the main thread exits, the sub-threads exit directly after it, regardless of whether they finish running or not. self.myThread .start() def print1(self): for i in range(100): tip_content = f'{i}th print - I am hero' self.run_log_print(message=tip_content) time.sleep(0.1) # sleep self.run_log_print(message='I am hero 1 - print done') def print2(self): for i in range(100, 200): tip_content = f'{i}th print - I am hero 2' self.run_log_print(message=tip_content) time.sleep(0.05) # sleep self.run_log_print(message='I am hero 2 - print done') def run_log_print(self, message): self.run_log.config(state=tk.NORMAL) self.run_log.insert(tk.END, "\n" + message + "\n") self.run_log.see(tk.END) self.run_log.update() self.run_log.config(state=tk.DISABLED) def clos_window(self): ans = askyesno(title='Hero v1.1 warning', message='Are you sure to exit the program?\nYes to exit, otherwise continue!') if ans: self.init_window_name.destroy() sys.exit() else: return None if __name__ == '__main__': """ Packing the button method into a thread to run without lagging """ """ Instantiate a parent window """ init_window = tk.Tk() """ set tk interface top """ init_window.attributes("-topmost", 1) """ Creating a Gui Class Object """ test_gui = TestGui(init_window) """ Initializing GUi Components """ init_window.mainloop()