Reputation: 61
this is the code that i used to load a gif into a label object in tkinter
class ImageLabel(tk.Label):
"""a label that displays images, and plays them if they are gifs"""
def load(self, im):
if isinstance(im, str):
im = Image.open(im)
print(im.is_animated)
print(im.n_frames)
self.loc = 0
self.frames = []
try:
for i in count(1):
self.frames.append(ImageTk.PhotoImage(im.copy()))
im.seek(i)
except EOFError:
pass
try:
self.delay = im.info['duration']
except:
self.delay = 900
if len(self.frames) == 1:
self.config(image=self.frames[0])
else:
self.next_frame()
def unload(self):
self.config(image="")
self.frames = None
def next_frame(self):
if self.frames:
self.loc += 1
self.loc %= len(self.frames)
self.config(image=self.frames[self.loc])
self.after(self.delay, self.next_frame)
my aim is to load the gif in only a single loop based on the number of frames like lets say there are 5 frames in an image it only loops through that and stops
can someone help me with this.
if i change the
for i in count(im.n_frames):
it only loads the first frame and stops after that.
Upvotes: 0
Views: 462
Reputation: 46786
If you want to play the animation of GIF image only once, you need to modify next_frame()
not to call .after()
when the last frame has been shown.
Below is the modified ImageLabel
class:
class ImageLabel(tk.Label):
"""a label that displays images, and plays them if they are gifs"""
def load(self, im):
if isinstance(im, str):
im = Image.open(im)
print(im.is_animated)
print(im.n_frames)
self.delay = im.info.get('duration', 900)
# load all the frames inside the image
self.frames = []
for i in range(im.n_frames):
im.seek(i)
self.frames.append(ImageTk.PhotoImage(im.copy()))
# start the animation
self.next_frame()
def unload(self):
self.config(image="")
self.frames = None
# modified to play the animation only once
def next_frame(self, loc=0):
self.config(image=self.frames[loc])
if loc < len(self.frames)-1:
self.after(self.delay, self.next_frame, loc+1)
Upvotes: 0
Reputation: 355
This is line for line an answer provided as to how to get tkinter to loop a gif indefinitely (except that you changed the duration of the delay).
I'm not sure you realize what count is doing here. Count, imported from itertools, is going to infintely count (acting as a "while(true)" but incrementing a number) unless given a barrier. It accepts two parameters (start= , stop= ) but if only given one, it defaults to start. So you have initiated a count at the value of im.n_frames.
What's happening is that you are loading the first frame, and starting the count at the last frame. When it then goes to find the next frame, you're hitting EOF, and starting the whole thing over again.
If the images are indexed starting at 1, try
for i in range(1, im.n_frames+1):
Upvotes: 0
Reputation: 61
there are two things that would be required to make this work in this code snippet
Number 1 change the loc intially to -1 secondly change the next_frame function to
def next_frame(self):
if self.frames:
self.loc += 1
self.config(image=self.frames[self.loc])
self.after(self.delay, self.next_frame)
Upvotes: 1