Python编程实例-Tkinter GUI编程-异步编程-after()函数
异步编程-after()函数
在本文中,将介绍如何使用 Tkinter after() 方法在超时后的调度操作。
1、Tkinter的after()介绍
所有 Tkinter 小部件都有 after() 方法,语法如下:
after(delay, callback=None)
1
after() 方法在 Tkinter 的主循环中延迟毫秒 (ms) 后调用回调函数一次。
如果不提供回调,则 after() 方法的行为类似于 time.sleep() 函数。** after()** 方法使用毫秒而不是秒作为单位。
2、完整示例
import tkinter as tk
from tkinter import ttk
import time
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Tkinter after() Demo')
self.geometry('300x100')
self.style = ttk.Style(self)
self.button = ttk.Button(self, text='Wait 3 seconds')
self.button['command'] = self.start
self.button.pack(expand=True, ipadx=10, ipady=5)
def start(self):
self.change_button_color('red')
time.sleep(3)
self.change_button_color('black')
def change_button_color(self, color):
self.style.configure('TButton', foreground=color)
if __name__ == "__main__":
app = App()
app.mainloop()
示例程序由一个按钮组成。 当单击按钮时:
首先,按钮的颜色变为红色。
然后,程序休眠 3 秒。
最后,按钮的颜色变为黑色。
但是,当运行程序并单击按钮时,会注意到按钮的颜色根本没有改变。 此外,GUI 冻结 3 秒:
原因是 sleep() 函数暂停了主线程的执行。 因此,Tkinter 无法更新 GUI。
要解决此问题,可以使用 after() 方法来安排更新按钮颜色的操作,而不是暂停主线程执行:
import tkinter as tk
from tkinter import ttk
import time
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title('Tkinter `after()` Demo')
self.geometry('300x100')
self.style = ttk.Style(self)
self.button = ttk.Button(self, text='Wait 3 seconds')
self.button['command'] = self.start
self.button.pack(expand=True, ipadx=10, ipady=5)
def start(self):
self.button.after(3000,self.update)
def change_button_color(self, color):
self.style.configure('TButton', foreground=color)
def update(self):
self.change_button_color('red')
if __name__ == "__main__":
app = App()
app.mainloop()
3、为什么使用 Tkinter after() 方法
一个 Python 程序可以有一个或多个线程。 当启动 Tkinter 应用程序时,它会在主线程中执行。Tkinter 的主循环必须从主线程开始。 它负责处理事件和更新 GUI。如果在主线程中启动一个长时间运行的任务,GUI 将冻结并且不响应用户事件。为了防止长时间运行的任务阻塞主线程,可以使用 after() 方法安排一个不会早于指定时间执行的操作。当主线程不忙时,Tkinter 会在主线程中执行回调。
一个典型的应用示例,以下程序显示一个数字时钟。 它使用 after() 方法每秒更新当前时间:
import tkinter as tk
from tkinter import ttk
import time
class DigitalClock(tk.Tk):
def __init__(self):
super().__init__()
# configure the root window
self.title('Digital Clock')
self.resizable(0, 0)
self.geometry('250x80')
self['bg'] = 'black'
# change the background color to black
self.style = ttk.Style(self)
self.style.configure(
'TLabel',
background='black',
foreground='red')
# label
self.label = ttk.Label(
self,
text=self.time_string(),
font=('Digital-7', 40))
self.label.pack(expand=True)
# schedule an update every 1 second
self.label.after(1000, self.update)
def time_string(self):
return time.strftime('%H:%M:%S')
def update(self):
""" update the label every 1 second """
self.label.configure(text=self.time_string())
# schedule another timer
self.label.after(1000, self.update)
if __name__ == "__main__":
clock = DigitalClock()
clock.mainloop()
运行结果:
代码如何运行?
第一步,以字符串格式返回当前时间
def time_string(self):
return time.strftime('%H:%M:%S')
1
2
__init__()方法使用 after() 方法来安排一个动作,每秒将当前时间更新到标签:
self.label.after(1000, self.update)
1
第二步,在 update() 方法中,将当前时间更新为标签,并在一秒后安排另一次更新
def update(self):
""" update the label every 1 second """
self.label.configure(text=self.time_string())
# schedule another timer
self.label.after(1000, self.update)
总结
使用 Tkinter after() 方法安排将在超时后运行的操作
传递给 after() 方法的回调仍然在主线程中运行。 因此,应该避免使用 after() 方法执行长时间运行的任务。
————————————————
版权声明:本文为CSDN博主「视觉智能」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wujuxKkoolerter/article/details/124208097