22

I've been trying to play an animated gif using Tkinter.PhotoImage, but haven't been seeing any success. It displays the image, but not the animation. The following is my code:

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

It displays the image in a window, and that's it. I'm thinking that the issue has something to do with Tkinter.Label but I'm not sure. I've looked for solutions but they all tell me to use PIL (Python Imaging Library), and it's something that I don't want to use.

With the answer, I created some more code (which still doesn't work...), here it is:

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()

Thanks for everything! :)

Zizouz212
  • 4,908
  • 5
  • 42
  • 66
  • 1
    You could check if it has something to with being attached to a `Label` widget by using it instead on a `Canvas` widget (`C.create_image(x, y, image=photo`). – martineau Feb 14 '15 at 18:13
  • I don't know if I'm doing something wrong with `Canvas` but I only get the bottom right corner of my image and it looks pixelated... – Zizouz212 Feb 15 '15 at 21:26
  • 1
    Try getting it working with a non-animated image first, then switch to an animated one afterward. – martineau Feb 15 '15 at 21:38
  • Same thing happens with non-animated gif... – Zizouz212 Feb 15 '15 at 21:41
  • 1
    All I can say without seeing the code is that you must be doing it wrong. – martineau Feb 15 '15 at 21:49
  • Another question here (that's mine): http://stackoverflow.com/questions/28531415/tkinter-animation-will-not-work – Zizouz212 Feb 15 '15 at 21:52
  • For what it's worth, here's [example code](https://www.daniweb.com/software-development/python/code/216550/tkinter-to-put-a-gif-image-on-a-canvas-python) showing how to put a gif image on a `Canvas` with Tkinter. – martineau Feb 16 '15 at 05:03

2 Answers2

21

You have to drive the animation yourself in Tk. An animated gif consists of a number of frames in a single file. Tk loads the first frame but you can specify different frames by passing an index parameter when creating the image. For example:

frame2 = PhotoImage(file=imagefilename, format="gif -index 2")

If you load up all the frames into separate PhotoImages and then use timer events to switch the frame being shown (label.configure(image=nextframe)). The delay on the timer lets you control the animation speed. There is nothing provided to give you the number of frames in the image other than it failing to create a frame once you exceed the frame count.

See the photo Tk manual page for the official word.

patthoyts
  • 32,320
  • 3
  • 62
  • 93
  • 7
    Sounds like a t[Kludge](https://en.wikipedia.org/wiki/Kludge). – martineau Feb 15 '15 at 21:35
  • And I should also ask if there is a way to determine the number of frames for an image; Tried this: http://stackoverflow.com/questions/7503567/python-how-i-can-get-gif-frames/7504131#7504131 Also, for 2500 images, is there a way to ever make it automatic? – Zizouz212 Feb 15 '15 at 21:45
  • See http://en.wikipedia.org/wiki/GIF#Animated_GIF for the layout. The GIF file does not contain a number of frames - only the delay per frame which may be variable. – patthoyts Feb 16 '15 at 09:15
  • Could you please provide a verificable example for this? – Ariel Montes Jan 19 '21 at 13:26
13

Here's a simpler example without creating an object:

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()
Alex
  • 131
  • 1
  • 2
  • 15
    Can you explain your code, so that others can learn from it instead of copy&pasting some piece of code that may or may not work? – Robert Mar 19 '17 at 03:35
  • It looks like it may work, but it kicks out a list index out of range for frame = frames[ind] – Joe Kissling Mar 24 '17 at 06:25
  • 2
    @Apostolos: It is because you tried to load 100 frames, but the gif that you used has less than 100 frames. Try reducing the 100 frames to 10 and gradually increase it until you hit an error. – Raj Mehta Sep 18 '18 at 18:52
  • 1
    I see. This is obviously the case. So, this time I used a GIF file with 32 frames and replaced 100 by 32. When all frames are displayed in the animation, I still get "IndexError: list index out of range". Anyway, I have created my own program that also counts the frames ... Moreover, it is also very smooth ... in the above example frame sizes change and the effect is very bad. I hope you have straightened this up. – Apostolos Sep 21 '18 at 10:37
  • A pretty interesting way, though it will work the right way only for GIFs with exactly 100 frames. – Demian Wolf Apr 22 '20 at 17:08
  • @Apostolos Care to share? – Robin Andrews May 15 '20 at 06:40
  • Share what? I can't find any solution I've given … Besides, this is 2 years old and I can don't even remember what's the issue! – Apostolos May 16 '20 at 08:14