Python:让gif在线程运行时用TKinter制作动画

2024-10-03 13:27:02 发布

您现在位置:Python中文网/ 问答频道 /正文

所以,我相信你可以从我冗长的主题中看出我的要求,但我要重申一下。我试图让一个gif动画,而在后台线程正在运行一个计算与在TKinter。为了简单起见,我使用这个gif:http://i.imgur.com/4Y9UJ.gif

gif动画当前正在运行,您可以看到是否运行脚本。但是一旦按下Generate按钮并启动线程,gif就会暂停直到完成。我在用时间。睡觉()模拟我将在后台进行的大量计算(尽管我不确定这是否是导致问题的真正原因)。在

我敢肯定这和不理解动画的运作方式有关。有什么建议吗?在

代码如下:

from Tkinter import *
import tkMessageBox
import time
import os
import threading
from PIL import Image, ImageTk

class Gif(Label):
    def __init__(self, master, filename):
        evanGif = Image.open(filename)
        gifSeq = []
        try:
            while 1:
                gifSeq.append(evanGif.copy())
                evanGif.seek(len(gifSeq)) # skip to next frame
        except EOFError:
            pass # we're done
        try:
            #Special case for the evangalion gif
            if evanGif.info['duration'] == 0:
                self.delay = 100
            else:
                self.delay = evanGif.info['duration']
        except KeyError:
            self.delay = 100
        gifFirst =gifSeq[0].convert('RGBA')
        self.gifFrames = [ImageTk.PhotoImage(gifFirst)]

        Label.__init__(self, master, image=self.gifFrames[0])

        temp =gifSeq[0]
        for image in gifSeq[1:]:
            temp.paste(image)
            frame = temp.convert('RGBA')
            self.gifFrames.append(ImageTk.PhotoImage(frame))

        self.gifIdx = 0
        self.cancel = self.after(self.delay, self.play)

    def play(self):
        self.config(image=self.gifFrames[self.gifIdx])
        self.gifIdx += 1
        if self.gifIdx == len(self.gifFrames):
            self.gifIdx = 0
        self.cancel = self.after(self.delay, self.play)

class App:
    generating = False
    def __init__(self, master):
        self.master=master

        #Initializing frames
        self.buttonFrame = Frame(master, background='light gray')
        self.loadingFrame = Frame(master, background='light gray')
        self.loadingFrame.grid(row=0)
        self.buttonFrame.grid(row=1)
        self.anim = Gif(self.loadingFrame, '4Y9UJ.gif').pack()
        self.update_Thread = threading.Thread(target=time.sleep, args=(5,))
        self.buttonSetup()

    def buttonSetup(self):
        #ALL THE BUTTONS
        self.generateBt = Button(self.buttonFrame, text="Generate!", command=self.generate, background='light gray', highlightbackground='light gray')
        self.generateBt.pack(side=LEFT)
        self.quitBt = Button(self.buttonFrame, text="Quit!", fg="red", command=self.buttonFrame.quit, background='light gray', highlightbackground='light gray')
        self.quitBt.pack(side=LEFT)

    def generate(self):
        self.hideForGen()
        self.update_Thread.start()
        while(self.update_Thread.isAlive()):
            self.master.update_idletasks()
        self.reset()
        self.master.update_idletasks()
        tkMessageBox.showinfo("Complete", "Report generation completed!")

    def hideForGen(self):
        self.buttonFrame.grid_forget()

    def reset(self):
        self.buttonFrame.grid(row=1)

root = Tk()
root.title('Test')
root.configure(background='light gray')
app = App(root)
root.mainloop()

Tags: importselfmasterdefupdategiflightbackground
2条回答

问题出在generate()方法中。 while循环是不必要的。在

记住,你不能重新开始一个线程。 如果要多次使用generate按钮,那么每次都需要创建一个新线程。在

class App:
    generating = False
    def __init__(self, master):
        self.master=master

        #Initializing frames
        self.buttonFrame = Frame(master, background='light gray')
        self.loadingFrame = Frame(master, background='light gray')
        self.loadingFrame.grid(row=0)
        self.buttonFrame.grid(row=1)
        self.anim = Gif(self.loadingFrame, '4Y9UJ.gif')
        self.anim.pack()
##        self.update_Thread = threading.Thread(target=time.sleep, args=(5,))

        self.buttonSetup()

    def buttonSetup(self):
        #ALL THE BUTTONS
        self.generateBt = Button(self.buttonFrame, text="Generate!", command=self.generate, background='light gray', highlightbackground='light gray')
        self.generateBt.pack(side=LEFT)
        self.quitBt = Button(self.buttonFrame, text="Quit!", fg="red", command=self.buttonFrame.quit, background='light gray', highlightbackground='light gray')
        self.quitBt.pack(side=LEFT)

    def wait_generate(self):
        if self.update_Thread.isAlive():
            self.master.after(500, self.wait_generate)
        else:
            tkMessageBox.showinfo("Complete", "Report generation completed!")
            self.reset()

    def generate(self):
        self.hideForGen()
        self.update_Thread = threading.Thread(target=time.sleep, args=(5,))
        self.update_Thread.start()
##        while(self.update_Thread.isAlive()):
##            self.master.update_idletasks()
##        self.reset()
##        self.master.update_idletasks()
##        tkMessageBox.showinfo("Complete", "Report generation completed!")
        self.wait_generate()

    def hideForGen(self):
        self.buttonFrame.grid_forget()

    def reset(self):
        self.buttonFrame.grid(row=1)

方法如下:

    def generate(self):
        self.hideForGen()
        self.update_Thread.start()
        while(self.update_Thread.isAlive()):
            self.master.update_idletasks()
        self.reset()
        self.master.update_idletasks()
        tkMessageBox.showinfo("Complete", "Report generation completed!")

如果你把

^{pr2}$

而不是

    self.master.update_idletasks()

它应该有用。至少对我来说是这样。在

相关问题 更多 >