python tkinter 使用PIL 显示动态图像GIF

4 投票
2 回答
17762 浏览
提问于 2025-04-17 05:22

有没有办法在Tkinter中用Python图像库显示一个动图GIF呢?

我原以为可以用ImageSequence模块来实现,但我不知道怎么用,也不确定是否可行。

第一个问题是有没有简单的方法。比如:用PIL和ImageSequence加载一个GIF,然后直接用ImageTk.PhotoImage在Tkinter窗口上画出来,这样就能动了。

还是说我得自己写个函数,使用after方法或者像time.sleep这样的东西,来循环播放GIF的每一帧,然后在Tkinter窗口上画出来?

第二个问题是:即使我需要写个函数来循环播放GIF的帧,ImageSequence模块本来就是用来做这个的吗,还是PIL还有其他模块可以用?

我现在用的是Python 3.1,还有一个PIL的私有版本,在这个话题中提到过。

2 个回答

0

简单的PIL版本:

canvas = Image.new("RGB",(Width,Height),"white")
gif = Image.open('text.gif', 'r')
frames = []
try:
    while 1:
        frames.append(gif.copy())
        gif.seek(len(frames))
except EOFError:
    pass

for frame in frames:
     canvas.paste(frame)
     canvas.show()
6

新sg组: comp.lang.python

发件人: "Fredrik Lundh"

日期: 2006年5月1日 星期一

Daniel Nogradi 写道:

‘1.1.4版本的源代码包里有一个Scripts目录,里面有player.py、gifmaker.py和explode.py,这些文件都是用来处理动画gif的。’

这些文件在1.1.5(和1.1.6)版本中也包含,应该可以正常使用。

如果你缺少的只是Scripts目录里的几个文件,可以在这里找到:

http://svn.effbot.org/public/pil/Scripts/


player.py是通过命令行运行的。

看看这个能不能对你有用:

from Tkinter import * 
from PIL import Image, ImageTk


class MyLabel(Label):
    def __init__(self, master, filename):
        im = Image.open(filename)
        seq =  []
        try:
            while 1:
                seq.append(im.copy())
                im.seek(len(seq)) # skip to next frame
        except EOFError:
            pass # we're done

        try:
            self.delay = im.info['duration']
        except KeyError:
            self.delay = 100

        first = seq[0].convert('RGBA')
        self.frames = [ImageTk.PhotoImage(first)]

        Label.__init__(self, master, image=self.frames[0])

        temp = seq[0]
        for image in seq[1:]:
            temp.paste(image)
            frame = temp.convert('RGBA')
            self.frames.append(ImageTk.PhotoImage(frame))

        self.idx = 0

        self.cancel = self.after(self.delay, self.play)

    def play(self):
        self.config(image=self.frames[self.idx])
        self.idx += 1
        if self.idx == len(self.frames):
            self.idx = 0
        self.cancel = self.after(self.delay, self.play)        


root = Tk()
anim = MyLabel(root, 'animated.gif')
anim.pack()

def stop_it():
    anim.after_cancel(anim.cancel)

Button(root, text='stop', command=stop_it).pack()

root.mainloop()

撰写回答