Skip to main content
 首页 » 编程设计

python之如何在 Tkinter 的透明启动画面中停止闪烁

2025年05月04日11emanlee

使用我在网上找到的一些用于创建通用 Tkinter 闪屏的修改代码,我尝试创建一个带有 .png 的透明闪屏之类的东西。我知道此代码仅适用于 Windows,对此我没有意见。

但是,我注意到图像在屏幕上绘制时出现闪烁( Canvas 区域在绘制图片之前是黑色的)。我不太了解它,但我怀疑它必须在谷歌搜索和阅读后对图像进行缓冲。我还读到 Canvas 支持双缓冲,所以闪烁不应该发生,所以可能是顶级小部件或其他东西。

无论如何,有什么办法可以解决这个问题吗?我真的很想为此继续使用 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() 

请您参考如下方法:

您应该遵循的一条经验法则是永远不要在 GUI 中调用 sleep。它完全按照它说的去做,它会让你的整个应用程序进入休眠状态。这意味着 GUI 无法重绘自身,这可能是导致闪烁的原因。

如果你想让一个窗口在一段时间后销毁,使用after方法。例如:

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

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

这使您有机会根据需要添加一点“淡出”效果。为此,您可以检查启动画面的 alpha 是否低于某个阈值(例如 10%)并将其销毁。如果不是,则将 alpha 降低 10% 并在 100 毫秒后再次调用该函数。