Python 使用Tkinter的动画gif中没有透明度

Python 使用Tkinter的动画gif中没有透明度,python,tkinter,transparency,animated-gif,Python,Tkinter,Transparency,Animated Gif,我想用Tkinter显示动画gif。我尝试使用提出的解决方案 问题是在我的gif中,只有第一帧是完整的。所有其他帧都由一个几乎透明的区域组成,其中只有少数改变w.r.t的像素。前一帧是不透明的 我能告诉Tkinter这些帧的背景应该是透明的吗 from Tkinter import * from PIL import Image, ImageTk class MyLabel(Label): def __init__(self, master, filename):

我想用Tkinter显示动画gif。我尝试使用提出的解决方案

问题是在我的gif中,只有第一帧是完整的。所有其他帧都由一个几乎透明的区域组成,其中只有少数改变w.r.t的像素。前一帧是不透明的

我能告诉Tkinter这些帧的背景应该是透明的吗

from Tkinter import * 
from PIL import Image, ImageTk


class MyLabel(Label):
    def __init__(self, master, filename):
        im = Image.open(filename)
        seq =  []
        try:
            while 1:
                seq.append(im.copy())
                im.seek(len(seq)) # skip to next frame
        except EOFError:
            pass # we're done

        try:
            self.delay = im.info['duration']
        except KeyError:
            self.delay = 100

        first = seq[0].convert('RGBA')
        self.frames = [ImageTk.PhotoImage(first)]

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

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

        self.idx = 0

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

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


root = Tk()
anim = MyLabel(root, 'animated.gif')
anim.pack()

def stop_it():
    anim.after_cancel(anim.cancel)

Button(root, text='stop', command=stop_it).pack()

root.mainloop()

看起来您需要为粘贴操作提供掩码:

from Tkinter import * 
from PIL import Image, ImageTk


class MyLabel(Label):
    def __init__(self, master, filename):
        im = Image.open(filename)
        seq =  []
        try:
            while 1:
                seq.append(im.copy())
                im.seek(len(seq)) # skip to next frame
        except EOFError:
            pass # we're done

        try:
            self.delay = im.info['duration']
        except KeyError:
            self.delay = 100

        first = seq[0].convert('RGBA')
        self.frames = [ImageTk.PhotoImage(first)]

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

        lut = [1] * 256
        lut[im.info["transparency"]] = 0

        temp = seq[0]
        for image in seq[1:]:
            mask = image.point(lut, "1")
            # point() is used to map image pixels into mask pixels
            # via the lookup table (lut), creating a mask
            # with value 0 at transparent pixels and
            # 1 elsewhere
            temp.paste(image, None, mask) #paste with mask
            frame = temp.convert('RGBA')
            self.frames.append(ImageTk.PhotoImage(frame))

        self.idx = 0

        self.cancel = self.after(1000, self.play)

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


root = Tk()
anim = MyLabel(root, 'tumblr_m3i10ma4fI1qe0eclo1_r9_500.gif')
anim.pack()

def stop_it():
    anim.after_cancel(anim.cancel)

Button(root, text='stop', command=stop_it).pack()

root.mainloop()

我不明白你在问什么。在某一点上,你说除了改变的像素外,所有的东西都是透明的,然后你问如何使背景透明。这是如何结合在一起的?另外,你可以链接到一个动画,透明的gif进行测试,这样我们就不必自己搜索了吗?以这个gif为例:像素应该是透明的。但是当我用TKinter加载单个帧时,透明像素只是黑色的。我想我必须告诉Tkinter,在某一点上,帧中某一颜色的所有像素都应该是透明的。我自己就试过了。对于GIF,我看到了同样的问题,除了“透明”像素不是黑色,而是标签的
bg
,因此“主”帧似乎在此处被覆盖(但保留在边框处)。另外,当我用GIMP(一个带有透明背景的简单旋转十字)创建一个简单的动画GIF时,效果很好,但是在第一帧不透明的情况下(就像你的例子),我又遇到了同样的问题。我的猜测是,Tkinter不是将图像堆叠在一起,而是替换新的部分,即没有“累积”模式。是的,我也这么想。这可能是Panel小部件的一个限制。我现在正在尝试使用画布小部件,但迄今为止没有成功。也许你可以在画布上绘制第一帧,然后在画布上绘制其他帧,也就是说,不替换第一帧。