我不是 100% 确定我理解了这个问题,但我将描述如何为图像设置动画。
Tkinter 不包含动画图像的功能,因此您必须自己编写它们。您必须提取所有子图像、子图像持续时间,然后构建一个序列器以在您的显示器上交换子图像。
Pillow 可以提取图像序列。 WEBP 图像似乎只支持一个帧持续时间,而 GIF 图像可能对每个子图像具有不同的帧持续时间。即使有很多,我也会只对 GIF 图像使用第一个持续时间。据我所知,Pillow 不支持从 WEBP 图像获取帧持续时间,但您可以从文件中读取它,请参阅WebP Container Specification。
示例实现:
import tkinter as tk
from PIL import Image, ImageTk, ImageSequence
import itertools
root = tk.Tk()
display = tk.Label(root)
display.pack(padx=10, pady=10)
filename = 'images/animated-nyan-cat.webp'
pil_image = Image.open(filename)
no_of_frames = pil_image.n_frames
# Get frame duration, assuming all frame durations are the same
duration = pil_image.info.get('duration', None) # None for WEBP
if duration is None:
with open(filename, 'rb') as binfile:
data = binfile.read()
pos = data.find(b'ANMF') # Extract duration for WEBP sequences
duration = int.from_bytes(data[pos+12:pos+15], byteorder='big')
# Create an infinite cycle of PIL ImageTk images for display on label
frame_list = []
for frame in ImageSequence.Iterator(pil_image):
cp = frame.copy()
frame_list.append(cp)
tkframe_list = [ImageTk.PhotoImage(image=fr) for fr in frame_list]
tkframe_sequence = itertools.cycle(tkframe_list)
tkframe_iterator = iter(tkframe_list)
def show_animation():
global after_id
after_id = root.after(duration, show_animation)
img = next(tkframe_sequence)
display.config(image=img)
def stop_animation(*event):
root.after_cancel(after_id)
def run_animation_once():
global after_id
after_id = root.after(duration, run_animation_once)
try:
img = next(tkframe_iterator)
except StopIteration:
stop_animation()
else:
display.config(image=img)
root.bind('<space>', stop_animation)
# Now you can run show_animation() or run_animation_once() at your pleasure
root.after(1000, run_animation_once)
root.mainloop()
有一些库,比如 imgpy,支持 GIF 动画,但我没有使用任何此类库的经验。
加法
duration 变量设置动画速率。要减慢速度,只需增加持续时间即可。
将动画放在画布上的最简单方法就是将标签放在画布上,参见下面的示例:
# Replace this code
root = tk.Tk()
display = tk.Label(root)
display.pack(padx=10, pady=10)
# with this code
root = tk.Tk()
canvas = tk.Canvas(root, width=500, height=500)
canvas.pack(padx=10, pady=10)
display = tk.Label(canvas)
window = canvas.create_window(250, 250, anchor='center', window=display)
那么您不必更改程序中的任何其他内容。