# Author: Miguel Martinez Lopez
from Tkinter import PhotoImage
from ttk import Label
from PIL import Image, ImageTk
class AnimatedGIF(Label, object):
def __init__(self, master, path, forever=True):
self._master = master
self._loc = 0
self._forever = forever
self._is_running = False
im = Image.open(path)
self._frames = []
i = 0
try:
while True:
frame = ImageTk.PhotoImage(im.copy().convert('RGBA'))
self._frames.append(frame)
i += 1
im.seek(i)
except EOFError: pass
self._last_index = len(self._frames) - 1
try:
self._delay = im.info['duration']
except:
self._delay = 100
self._callback_id = None
super(AnimatedGIF, self).__init__(master, image=self._frames[0])
def start_animation(self, beginning=False):
if self._is_running: return
if beginning:
self._loc = 0
self.configure(image=self._frames[0])
self._master.after(self._delay, self._animate_GIF)
self._is_running = True
def stop_animation(self):
if not self._is_running: return
if self._callback_id is not None:
self.after_cancel(self._callback_id)
self._callback_id = None
self._is_running = False
def _animate_GIF(self):
self._loc += 1
self.configure(image=self._frames[self._loc])
if self._loc == self._last_index:
if self._forever:
self._loc = 0
self._callback_id = self._master.after(self._delay, self._animate_GIF)
else:
self._callback_id = None
else:
self._callback_id = self._master.after(self._delay, self._animate_GIF)
def pack(self, start_animation=True, **kwargs):
if start_animation:
self.start_animation()
super(AnimatedGIF, self).pack(**kwargs)
def grid(self, start_animation=True, **kwargs):
if start_animation:
self.start_animation()
super(AnimatedGIF, self).grid(**kwargs)
def place(self, start_animation=True, **kwargs):
if start_animation:
self.start_animation()
super(AnimatedGIF, self).place(**kwargs)
def pack_forget(self, **kwargs):
self.stop_animation()
super(AnimatedGIF, self).pack_forget(**kwargs)
def grid_forget(self, **kwargs):
self.stop_animation()
super(AnimatedGIF, self).grid_forget(**kwargs)
def place_forget(self, start_animation=True, **kwargs):
self.stop_animation()
super(AnimatedGIF, self).place_forget(**kwargs)
if __name__ == "__main__":
from Tkinter import Tk, Label
root = Tk()
# Add the path to a GIF to make the example working
l = AnimatedGIF(root, "path to GIF")
l.pack()
root.mainloop()
Diff to Previous Revision
--- revision 4 2017-01-28 00:32:28
+++ revision 5 2017-04-10 11:13:04
@@ -8,23 +8,26 @@
class AnimatedGIF(Label, object):
- def __init__(self, master, path_to_gif):
+ def __init__(self, master, path, forever=True):
self._master = master
self._loc = 0
+ self._forever = forever
- im = Image.open(path_to_gif)
+ self._is_running = False
+
+ im = Image.open(path)
self._frames = []
i = 0
try:
while True:
- temp = im.copy()
- self._frames.append(ImageTk.PhotoImage(temp.convert('RGBA')))
+ frame = ImageTk.PhotoImage(im.copy().convert('RGBA'))
+ self._frames.append(frame)
i += 1
im.seek(i)
except EOFError: pass
- self._len = len(self._frames)
+ self._last_index = len(self._frames) - 1
try:
self._delay = im.info['duration']
@@ -34,26 +37,71 @@
self._callback_id = None
super(AnimatedGIF, self).__init__(master, image=self._frames[0])
-
- def _run(self):
+
+ def start_animation(self, beginning=False):
+ if self._is_running: return
+
+ if beginning:
+ self._loc = 0
+ self.configure(image=self._frames[0])
+
+ self._master.after(self._delay, self._animate_GIF)
+ self._is_running = True
+
+ def stop_animation(self):
+ if not self._is_running: return
+
+ if self._callback_id is not None:
+ self.after_cancel(self._callback_id)
+ self._callback_id = None
+
+ self._is_running = False
+
+ def _animate_GIF(self):
self._loc += 1
- if self._loc == self._len:
- self._loc = 0
+ self.configure(image=self._frames[self._loc])
- self.configure(image=self._frames[self._loc])
- self._callback_id = self._master.after(self._delay, self._run)
+ if self._loc == self._last_index:
+ if self._forever:
+ self._loc = 0
+ self._callback_id = self._master.after(self._delay, self._animate_GIF)
+ else:
+ self._callback_id = None
+ else:
+ self._callback_id = self._master.after(self._delay, self._animate_GIF)
- def pack(self, *args, **kwargs):
- self._run()
- super(AnimatedGIF, self).pack(*args, **kwargs)
+ def pack(self, start_animation=True, **kwargs):
+ if start_animation:
+ self.start_animation()
- def grid(self, *args, **kwargs):
- self._run()
- super(AnimatedGIF, self).grid(*args, **kwargs)
+ super(AnimatedGIF, self).pack(**kwargs)
+
+ def grid(self, start_animation=True, **kwargs):
+ if start_animation:
+ self.start_animation()
+
+ super(AnimatedGIF, self).grid(**kwargs)
- def place(self, *args, **kwargs):
- self._run()
- super(AnimatedGIF, self).place(*args, **kwargs)
+ def place(self, start_animation=True, **kwargs):
+ if start_animation:
+ self.start_animation()
+
+ super(AnimatedGIF, self).place(**kwargs)
+
+ def pack_forget(self, **kwargs):
+ self.stop_animation()
+
+ super(AnimatedGIF, self).pack_forget(**kwargs)
+
+ def grid_forget(self, **kwargs):
+ self.stop_animation()
+
+ super(AnimatedGIF, self).grid_forget(**kwargs)
+
+ def place_forget(self, start_animation=True, **kwargs):
+ self.stop_animation()
+
+ super(AnimatedGIF, self).place_forget(**kwargs)
if __name__ == "__main__":
from Tkinter import Tk, Label
@@ -61,7 +109,7 @@
root = Tk()
# Add the path to a GIF to make the example working
- l = AnimatedGIF(root, "path to gif")
+ l = AnimatedGIF(root, "path to GIF")
l.pack()
root.mainloop()