Python:在线程运行时使用TKinter对gif进行动画处理

时间:2012-07-16 01:44:52

标签: python tkinter python-2.7 animated-gif

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

如果您运行脚本,gif动画当前正在运行。但是一旦按下Generate按钮并且线程启动,gif就会暂停直到它完成。我正在使用time.sleep()来模拟我将在后台进行的大量计算(虽然我不确定这是否是导致问题的原因)。

我确信它与不完全理解动画的运作方式有关。有什么建议吗?

代码如下:

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

2 个答案:

答案 0 :(得分: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!")

如果你把

    self.master.update()

而不是

    self.master.update_idletasks()

它应该有用。至少它对我有用。

答案 1 :(得分:1)

麻烦在于您的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)