淡入淡出小部件或图片 - Tkinter

时间:2017-05-24 23:50:00

标签: python-3.x tkinter

How to fade in/out on a Tkinter Frame
此问题表明您不能使用Tkinter的默认透明度来淡入和淡出使用窗口小部件。但是,有没有其他方法,使用PIL或其他方式,淡入淡出Tkinter中的小部件(或图片)? (即透明度可调)

1 个答案:

答案 0 :(得分:1)

(希望)简单的答案:

#!python3

import tkinter as tk
from PIL import Image, ImageTk
import os

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Image Fading")
        self.label = tk.Label(self)
        self.label.pack()
        self.load_pictures()
        self.fadetime = 1 # time between alpha channel changes in ms
        self.fadestep = 5 # change to alpha channel
        self.curstep = 0 # the current step through the transparency

        self.im = None # to hold the raw picture
        self.photo = None # to hold the tk compatible picture

        self.after(self.fadetime, self.fade_in)

    def fade_in(self):
        if not self.im:
            self.load_picture()
        alpha = min(self.curstep * self.fadestep, 255) # clamp to 255 maximum
        self.im.putalpha(alpha)
        self.photo = ImageTk.PhotoImage(self.im)
        self.label.configure(image=self.photo)
        self.curstep += 1
        print('fade in: %i' % alpha)
        if alpha == 255:
            self.curstep = 0
            self.after(3000, self.fade_out) # wait three seconds then fade out
        else:
            self.after(self.fadetime, self.fade_in)

    def fade_out(self):
        alpha = max(255 - self.curstep * self.fadestep, 0) # clamp to 0 minimum
        self.im.putalpha(alpha)
        self.photo = ImageTk.PhotoImage(self.im)
        self.label.configure(image=self.photo)
        self.curstep += 1
        print('fade out: %i' % alpha)
        if alpha == 0:
            self.curstep = 0
            self.im = None
            self.index += 1 # to use next picture
            if self.index >= len(self.filenames):
                self.index = 0
            self.after(3000, self.fade_in) # wait three seconds then load next picture
        else:
            self.after(self.fadetime, self.fade_out)

    def load_picture(self):
        while True:
            file = open(self.filenames[self.index], mode='rb')
            try: # if errors opening file as image, ignore and try next one
                self.im = Image.open(file) # this is a lazy operation and only reads image header
                self.im.load() # force image load here
                file.close() # close the file
                print('loaded: %s' % self.filenames[self.index])
                break
            except:
                file.close()
                self.index += 1
                if self.index >= len(self.filenames):
                    self.index = 0

    def load_pictures(self):
        self.filenames = []
        for file in os.listdir():
            if file.rsplit('.', 1)[-1] not in ['db', 'py', 'pyw']:
                self.filenames.append(file)
        self.index = -1

if __name__ == '__main__':
    app = App()
    app.mainloop()

这假设你想要将每个图像淡出然后是下一个图像,而不是从一个图像直接淡化到另一个图像。 请注意,尽管以最简单的方式(使用putalpha)执行此类淡入/淡出操作仍然是cpu密集型的,因为每次尝试都会转换为ImageTk实例。 这就是为什么我把变量用于alpha步长和时间来控制需要调用它的次数。

如果我的假设是错误的并且您需要从一个直线淡入到下一个,那么它会更加密集,因为您需要在将Alpha通道应用到每个图像后将图像“混合”在一起,然后将结果转换为ImageTk实例