after
方法介绍
tkinter窗口和组件都有一个after方法。此方法执行后,将会在规定的时间间隔之后,执行一个特定的您指定的函数。
如果在您指定的这个定时执行的函数中,再次调用after方法,就可以起到一个定时器的效果。其实,python中简单的定时器基本都是这个思路。
Tk类提供的after方法不是循环的计时器,不会堵塞进程的sleep。需要循环计时的话,就再在函数里面再次after
方法定义:
after(self, ms, func=None, *args)
在给定时间后调用函数一次。
- MS以毫秒为单位指定时间。
- func函数给出了要调用的函数。
- args额外的参数 作为函数调用的参数。
返回
调度的标识符,可使用after_cancel取消调度的标识符。
tkinter.Misc
def after_idle(self,
func: (...) -> Any,
*args: Any) -> str
如果Tcl主循环没有要处理的事件,则调用FUNC一次。
返回一个标识符以使用after_cancel取消计划。
tkinter.Misc
def after_cancel(self, id: str) -> None
取消ID标识的功能的调度。
- id: after或after_idle返回的标识符, 必须作为第一个参数给出。
例子:
下面是一个显示gif图像的例子。
需要注意使用after_cancel
的时机,并充分考虑各种异常情况不然就会导致有的时候没有正确停止递归。
from itertools import cycle
from PIL import ImageSequence
from PIL.ImageTk import PhotoImage
from PIL import Image as pil_image
class preview_gif:
def __init__(self, image_path: str, show_area):
# open the GIF and create a cycle iterator
self.show_area = show_area
self.image_path = image_path
self.updata_state = False # gif刷新状态
self.image_cycle = None # 轮询序列
self.framerate = None # 帧间隔
self.after_id = None
def next_frame(self):
"""更新帧"""
if self.updata_state:
image = next(self.image_cycle)
self.show_area.configure(image=image)
self.after_id = self.show_area.after(self.framerate, self.next_frame)
def start_show(self):
if self.after_id:
self.show_area.after_cancel(self.after_id) # 这个必须加防止出现前一个没停下两个一起动一张图加速播放
self.stop_show()
im = pil_image.open(self.image_path)
# 创建帧序列
sequence = ImageSequence.Iterator(im)
images = [PhotoImage(s) for s in sequence]
self.image_cycle = cycle(images)
self.framerate = im.info["duration"] # 帧间隔时间
self.updata_state = True
self.show_area.after(self.framerate, self.next_frame)
im.close()
def stop_show(self):
if self.updata_state:
self.updata_state = False # gif刷新状态
self.show_area.configure(image="")
self.image_cycle = None # 轮询序列
self.framerate = None # 帧间隔
self.after_id = None
if __name__ == '__main__':
from ttkbootstrap import Window, Label, Button
root = Window(size=(400, 500), title="after演示")
label = Label(root)
show_class = preview_gif("./12.gif", label)
start = Button(root, text="开始", command=show_class.start_show)
stop = Button(root, text="停止", command=show_class.stop_show)
label.place(relx=0, rely=0, relwidth=1, relheight=0.93)
start.place(relx=0.2, rely=0.93, relwidth=0.2, relheight=0.07)
stop.place(relx=0.6, rely=0.93, relwidth=0.2, relheight=0.07)
root.mainloop()