简体   繁体   English

如何仅运行一次 tkinter gif 循环

[英]how to run tkinter gif loop only ONCE

this is the code that i used to load a gif into a label object in tkinter这是我用来将 gif 加载到 tkinter 中的 label object 中的代码




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我的目标是根据帧数仅在单个循环中加载 gif,例如假设图像中有 5 帧它只会循环并停止

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.它只加载第一帧并在那之后停止。

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数字 1 将 loc 初始更改为 -1 其次将 next_frame function 更改为

 def next_frame(self):
        if self.frames:
            self.loc += 1
            self.config(image=self.frames[self.loc])
            self.after(self.delay, self.next_frame)

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).这是逐行提供的关于如何让 tkinter 无限期循环 gif 的答案(除非您更改了延迟的持续时间)。

I'm not sure you realize what count is doing here.我不确定你是否意识到 count 在这里做了什么。 Count , imported from itertools, is going to infintely count (acting as a "while(true)" but incrementing a number) unless given a barrier.从 itertools 导入的Count将无限计数(充当“while(true)”但增加一个数字),除非给定障碍。 It accepts two parameters (start=, stop= ) but if only given one, it defaults to start.它接受两个参数(start=, stop=),但如果只给定一个,则默认为 start。 So you have initiated a count at the value of im.n_frames.因此,您已经开始对 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.然后当它去寻找下一帧时,你正在点击EOF,并重新开始整个事情。

If the images are indexed starting at 1, try如果图像从 1 开始索引,请尝试

for i in range(1, im.n_frames+1):

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.如果你想只播放一次GIF图像的animation,你需要修改next_frame()不要在显示最后一帧时调用.after( .after()

Below is the modified ImageLabel class:下面是修改后的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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM