跳转至

§5.2 动态图片#

约 948 个字 29 行代码 预计阅读时间 8 分钟

一、解析 gif 的方式#

解析 gif 实际就是得到 gif 文件的每一帧信息并存储起来,根据不同的需求,tkintertools.PhotoImage 提供了两种解析 gif 的方式,分别是运行前解析和运行时解析。从名字上不难知道是什么意思。

1.1 运行前解析#

运行前解析会在 gif 图片进行展示之前就对其解析,这个过程会阻塞整个线程,当图片的总帧数很少的时候,影响不大,感觉不出来,但当文件的总帧数非常大,这种延迟就很明显,甚至导致窗口卡死或者无响应,如果在窗口出现之前就开始解析,那么窗口会一直等到解析完毕后再弹出,非常影响用户体验。

1.2 运行时解析#

运行时解析会在其他事件运行的同时同步地解析 gif 图片,解析的时候,整个窗口会略微卡顿,但启动速度会非常快。当然,这种解析只会持续一遍,当解析完成后,窗口就和运行前解析一样,不会有任何的卡顿。

1.3 解析方式的选取#

两种解析方式各有特点,按需选取合适的解析方式。一般来说,大文件一定要用运行时解析,不然阻塞时间会让你怀疑人生的……当然你也可以偷懒,全部用运行时解析,为什么可以偷懒呢?因为不用写解析部分的代码(别看我,我就是这么干的)。

二、运行前解析 gif#

我们通过 PhotoImage.parse 得到解析生成器,此生成器每次返回一个 int 类型的数据,以表示当前解析的帧数。我们需要遍历这个生成器来完成解析过程。以下是示例代码:

import tkintertools as tkt

root = tkt.Tk('运行前解析', 1280, 720)
canvas = tkt.Canvas(root, 1280, 720, 0, 0)
canvas_item_id = canvas.create_image(640, 360)

image = tkt.PhotoImage('example.gif')

for _ in image.parse():  # 解析过程
    pass  # 表面上,啥也没干,实际上,在解析……

image.start(canvas, canvas_item_id, interval=30)

root.mainloop()

猜你想问:为什么不直接给 PhotoImage 写一个简单方法来完成整个解析过程,非要写这么个麻烦的过程?

那必然,是有原因的啊!有些人可能需要知道当前解析到什么地步了,并在每个解析步骤设置回调函数(比如进度条的更新),于是就设计了这个生成器来完成这个功能,这些将在下一节中详细讲述。

三、运行时解析 gif#

运行时解析,想必大家应该都已经明白什么意思了,这里直接给代码了。为什么直接给代码呢?因为相比于上面代码,只有少,没有多的。

import tkintertools as tkt

root = tkt.Tk('运行前解析', 1280, 720)
canvas = tkt.Canvas(root, 1280, 720, 0, 0)
canvas_item_id = canvas.create_image(640, 360)

image = tkt.PhotoImage('example.gif')

# for _ in image.parse():  # 解析过程
#     pass  # 表面上,啥也没干,实际上,在解析……

image.start(canvas, canvas_item_id, interval=30)

root.mainloop()

你没看错,就是注释掉了解析部分的代码……具体区别,你运行一下总帧数比较大的 gif 文件就知道了。

四、gif 动图相关操作#

4.1 播放#

从上文中可以看出,PhotoImage.start 就是播放了。

警告

没事别调用两遍 start 方法,这样的话 gif 的播放会卡碟的……你可以试一试。

4.2 暂停或继续#

调用 PhotoImage.pause 可以暂停播放,调用 PhotoImage.play 可以继续播放。

此外,使对应的画布的 lock 属性为 False 时也将暂停播放,实则为减少不必要的性能消耗。如以下代码:

canvas.lock(False)

但并不推荐使用这种方式来播放和暂停动图,因为这会导致这个画布上的所有动图都暂停或者继续播放。同时,这个 lock 是调用其他功能的方法,只不过会顺便将 gif 暂停和播放。因此,慎用,最好不这样用。

4.3 终止#

通过调用方法 PhotoImage.stop 可以终止 gif 的播放,但注意,一旦终止无法通过方法 play 重新播放,只能重新通过方法 start 来重新播放!

欢迎在评论区留下你的想法


下面没有更多评论啦😆