使用Tkinter播放GIF中的动画

22
我一直在尝试使用Tkinter.PhotoImage播放一个动画gif,但一直没有成功。它会显示图像,但不会播放动画。以下是我的代码:

我一直在尝试使用Tkinter.PhotoImage播放一个动画gif,但一直没有成功。它会显示图像,但不会播放动画。以下是我的代码:

root = Tkinter.Tk()
photo = Tkinter.PhotoImage(file = "path/to/image.gif")
label = Tkinter.Label(image = photo)
label.pack()
root.mainloop()

它在窗口中显示图像,仅此而已。我认为问题与 Tkinter.Label 有关,但我不确定。我已经寻找了解决方案,但它们都告诉我要使用 PIL(Python Imaging Library),而这是我不想使用的。

有了答案后,我创建了一些代码(仍然无法工作...),以下是代码:

from Tkinter import *

def run_animation():
    while True:
        try:
            global photo
            global frame
            global label
            photo = PhotoImage(
                file = photo_path,
                format = "gif - {}".format(frame)
                )

            label.configure(image = nextframe)

            frame = frame + 1

        except Exception:
            frame = 1
            break

root = Tk()
photo_path = "/users/zinedine/downloads/091.gif"

photo = PhotoImage(
    file = photo_path,
    )
label = Label(
    image = photo
    )
animate = Button(
    root,
    text = "animate",
    command = run_animation
    )

label.pack()
animate.pack()

root.mainloop()

谢谢你做的一切! :)


1
你可以尝试在 Canvas 组件上使用它 (C.create_image(x, y, image=photo)),来检查它是否与 Label 组件的附加有关。 - martineau
1
首先尝试使用非动画图像使其正常工作,然后再切换到动画图像。 - martineau
同样的问题也发生在非动画GIF上... - Zizouz212
1
我在没有看到代码的情况下只能说你一定做错了。 - martineau
这里还有一个问题(是我的):http://stackoverflow.com/questions/28531415/tkinter-animation-will-not-work - Zizouz212
显示剩余2条评论
2个回答

21

您需要在Tk中自己驱动动画。一个动画gif由单个文件中的多个帧组成。Tk会加载第一帧,但是您可以在创建图像时通过传递索引参数来指定不同的帧。例如:

frame2 = PhotoImage(file=imagefilename, format="gif -index 2")
如果您将所有帧加载到单独的PhotoImages中,然后使用定时器事件切换显示的帧(label.configure(image=nextframe)),则定时器上的延迟时间可以让您控制动画速度。除了在超过帧计数时无法创建帧之外,没有提供任何东西来告诉您图像中帧的数量。
请参阅官方文档photo Tk手册页面。

7
听起来像是个Kludge - martineau
我还应该问一下是否有一种方法来确定图像的帧数;尝试过这个:https://dev59.com/e2s05IYBdhLWcg3wAdWT#7504131 另外,对于2500张图片,是否有一种自动化的方法? - Zizouz212
参见http://en.wikipedia.org/wiki/GIF#Animated_GIF以查看布局。GIF文件不包含帧数 - 只包括每帧可能变化的延迟。 - patthoyts
你能否提供一个可验证的例子呢? - Ariel Montes

13

这里有一个不需要创建对象的更简单的例子:

from tkinter import *
import time
import os
root = Tk()

frameCnt = 12
frames = [PhotoImage(file='mygif.gif',format = 'gif -index %i' %(i)) for i in range(frameCnt)]

def update(ind):

    frame = frames[ind]
    ind += 1
    if ind == frameCnt:
        ind = 0
    label.configure(image=frame)
    root.after(100, update, ind)
label = Label(root)
label.pack()
root.after(0, update, 0)
root.mainloop()

15
你能否解释一下你的代码,这样别人就可以从中学习,而不是复制粘贴一些可能有效也可能无效的代码片段呢? - Robert
看起来它可能会工作,但它会抛出一个“索引超出范围”的错误,因为frame = frames[ind]。 - Joe Kissling
2
@Apostolos:这是因为您尝试加载100帧,但您使用的gif图像少于100帧。尝试将100帧减少到10帧,并逐渐增加直到出现错误。 - Raj Mehta
1
我明白了。这显然是这种情况。所以,这一次我使用了一个有32帧的GIF文件,并将100替换为32。当所有帧都在动画中显示时,我仍然会得到“IndexError:list index out of range”的错误。无论如何,我已经创建了自己的程序,它也计算帧数...此外,它也非常流畅...在上面的例子中,帧大小会改变,效果非常糟糕。我希望你已经解决了这个问题。 - Apostolos
一种相当有趣的方法,但只有在帧数恰好为100的GIF图像中才能正常工作。 - Demian Wolf
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接