如何在Tkinter的透明Splash屏幕中停止闪烁?

时间:2013-05-30 03:32:09

标签: python canvas tkinter transparent splash

使用我在网上找到的一些修改后的代码来创建一个通用的Tkinter启动画面,我尝试用.png创建一个透明的启动画面。我知道这段代码只适用于Windows,我很好。

然而,我注意到它在画面上绘制时会有图像闪烁(画布区域在绘制图片之前是黑色的)。我不太了解它,但我怀疑它必须在谷歌搜索和阅读后缓冲图像。我还读到画布支持双缓冲,因此闪烁不应该发生,所以也许它是顶级小部件或其他东西。

在任何情况下都有解决方法吗?我真的想继续使用Tkinter,这将是一个巨大的失望,不能摆脱闪烁。这是我在下面使用的代码。

from Tkinter import *
import ttk
from PIL import Image, ImageTk
import time

class Splash:
    def __init__(self, root, filename, wait):
        self.__root = root
        #To use .pngs or .jpgs instead of just .bmps and .gifs, PIL is needed
        self.__file = ImageTk.PhotoImage(Image.open(filename))
        self.__wait = wait + time.clock()

    def __enter__(self):
        # Hide the root while it is built.
        self.__root.withdraw()
        # Create components of splash screen.
        window = Toplevel(self.__root)
        #Set splash window bg to transparent
        window.attributes('-transparent', '#FFFFFE')

        #Set canvas bg to transparent
        canvas = Canvas(window,bg="#FFFFFE")
        splash = self.__file
        # Get the screen's width and height.
        scrW = window.winfo_screenwidth()
        scrH = window.winfo_screenheight()
        # Get the images's width and height.
        imgW = splash.width()
        imgH = splash.height()
        # Compute positioning for splash screen.
        Xpos = (scrW - imgW) // 2
        Ypos = (scrH - imgH) // 2
        # Configure the window showing the logo.
        window.overrideredirect(True)
        window.geometry('+{}+{}'.format(Xpos, Ypos))
        # Setup canvas on which image is drawn.
        canvas.configure(width=imgW, height=imgH, highlightthickness=0)
        canvas.pack()
        # Show the splash screen on the monitor.
        canvas.create_image(imgW // 2, imgH // 2, image=splash)
        window.update()
        # Save the variables for later cleanup.
        self.__window = window
        self.__canvas = canvas
        self.__splash = splash

    def __exit__(self, exc_type, exc_val, exc_tb):
        # Ensure that required time has passed.
        now = time.clock()
        if now < self.__wait:
            time.sleep(self.__wait - now)
        # Free used resources in reverse order.
        del self.__splash
        self.__canvas.destroy()
        self.__window.destroy()
        # Give control back to the root program.
        self.__root.update_idletasks()
        self.__root.deiconify()

 if __name__ == '__main__':
 #thread2 = myLazyDoStuffThread()

 root = Tk()
 with Splash(root,'splash.png',3):
      myprog = ApplyGUIAndOtherThings(root)#,thread2)
 root.mainloop()

1 个答案:

答案 0 :(得分:1)

您应遵循的经验法则是永远不要在GUI中调用sleep。它完全符合它所说的,它会让你的整个应用程序都睡眠。这意味着GUI无法重绘,可能是您闪烁的原因。

如果您希望在一段时间后销毁窗口,请使用after方法。例如:

delta = (self.__wait - now) * 1000
self.after(delta, self.close)

您需要定义self.close来销毁窗口。

如果您愿意,这可以让您有机会添加一些“消失”效果。您可以通过检查启动屏幕的alpha是否低于某个阈值(例如,10%)并将其销毁来执行此操作。如果不是,请将alpha降低10%并在100 ms内再次调用该函数。