Tkinter窗口中透明背景

24
有没有办法使用Tkinter在Python 3.x中创建“加载屏幕”?我的意思是像Adobe Photoshop中的加载屏幕那样,具有透明度等效果。我已经成功地通过以下方式去掉了框架边框:
root.overrideredirect(1)

但如果我这样做:

root.image = PhotoImage(file=pyloc+'\startup.gif')
label = Label(image=root.image)
label.pack()

图像显示正常,但窗口背景是灰色而不是透明的。是否有办法在窗口中添加透明度,同时仍然正确显示图像?
9个回答

47

这是可能的,但这取决于操作系统。在Windows中可以使用以下方法:

import Tkinter as tk # Python 2
import tkinter as tk # Python 3
root = tk.Tk()
# The image must be stored to Tk or it will be garbage collected.
root.image = tk.PhotoImage(file='startup.gif')
label = tk.Label(root, image=root.image, bg='white')
root.overrideredirect(True)
root.geometry("+250+250")
root.lift()
root.wm_attributes("-topmost", True)
root.wm_attributes("-disabled", True)
root.wm_attributes("-transparentcolor", "white")
label.pack()
label.mainloop()

如何取消窗口的透明度? - JeanExtreme002
1
如果您要调用 root.attributes("-topmost", True),则 root.lift() 是无用的。 - TheLizzard

23

以下是针对macOS的解决方案:

import tkinter as tk

root = tk.Tk()
# Hide the root window drag bar and close button
root.overrideredirect(True)
# Make the root window always on top
root.wm_attributes("-topmost", True)
# Turn off the window shadow
root.wm_attributes("-transparent", True)
# Set the root window background color to a transparent color
root.config(bg='systemTransparent')

root.geometry("+300+300")

# Store the PhotoImage to prevent early garbage collection
root.image = tk.PhotoImage(file="photoshop-icon.gif")
# Display the image on a label
label = tk.Label(root, image=root.image)
# Set the label background color to a transparent color
label.config(bg='systemTransparent')
label.pack()

root.mainloop()

屏幕截图

(在macOS Sierra 10.12.21上测试通过)


2
非常感谢您的帮助。您能否解释一下为什么需要同时使用 root.wm_attributes("-transparent", True)root.config(bg='systemTransparent')?它们的作用是什么?虽然它们可以完美地工作,但解释有点含糊不清。 - Saransh Malik
1
不客气 :) 我尝试在答案的注释中进行了一些澄清。第一个命令通过关闭窗口阴影来“允许”窗口透明,第二个命令指定要使用的(透明)背景颜色(请参见此链接)。 - Josselin
1
@Josselin 您的评论 “#存储PhotoImage以防止早期垃圾收集” 是错误的,因为图像实际上不会超出范围。 - TheLizzard
1
@SiddharthDushantha root.overrideredirect(True)root.overrideredirect(1)是相同的。事实上,.overrideredirect应该输入一个布尔值。参考tcl官网 - TheLizzard
2
label.config(bg='systemTransparent') 在 MacOS BigSur 11.7 上会使窗口完全透明,包括图像。如果我不添加这行代码,则图像会有灰色背景。 - Aditya Mittal
显示剩余4条评论

9

在tkinter中,没有跨平台的方法只使背景透明。


有没有 Linux 的方法? - Meric Ozcan
@MericOzcan 我相信这是在 Linux 的窗口管理器中完成的。 - leopardxpreload
@MericOzcan 我放弃了Tkinter的方法后发了一个“Linux Way”的答案。我尝试了90分钟的Tkinter。 - WinEunuuchs2Unix

7

只需使用 root.config(bg=''),例如:

from tkinter import *
root = Tk()
root.configure(bg='')

3
至少在 Linux 上,这似乎是可行的——直到你移动窗口并意识到它包含了它所覆盖的内容的快照,而不是透明的。 - Shadow

3

很简单:使用root.attributes()

在您的情况下,应该像这样使用root.attributes("-alpha", 0.5),其中0.5是您想要的透明度,0表示完全透明,1表示不透明。


9
不,那并不是我真正想要的...我不希望整个东西都是透明的,只有背景需要透明。图片本身应该保持不透明。 - forumfresser

3
一种跨平台的解决方案:
from sys import platform
import tkinter as tk
root = tk.Tk()

if platform == "linux" or platform == "linux2":
    root.overrideredirect(True)
    root.wait_visibility(root)
    root.wm_attributes("-alpha", 0.5)
elif platform == "darwin":
    root.overrideredirect(True)
    # Make the root window always on top
    root.wm_attributes("-topmost", True)
    # Turn off the window shadow
    root.wm_attributes("-transparent", True)
    # Set the root window background color to a transparent color
    root.config(bg='systemTransparent')
    root.geometry("+300+300")
    # Store the PhotoImage to prevent early garbage collection
    root.image = tk.PhotoImage(file="photoshop-icon.gif")
    # Display the image on a label
    label = tk.Label(root, image=root.image)
    # Set the label background color to a transparent color
    label.config(bg='systemTransparent')
    label.pack()
elif platform == "win32":
    root.image = tk.PhotoImage(file='startup.gif')
    label = tk.Label(root, image=root.image, bg='white')
    root.overrideredirect(True)
    root.geometry("+250+250")
    root.lift()
    root.wm_attributes("-topmost", True)
    root.wm_attributes("-disabled", True)
    root.wm_attributes("-transparentcolor", "white")
    label.pack()

root.mainloop()

1
root.attributes("-transparentcolor", "white")中,使用另一种很少使用的颜色会更好。 如果您要调用 root.attributes("-topmost", True),则 root.lift()将是无用的。 而且没有必要使用 root.geometry("+250+250") - TheLizzard
@user3435121,你使用哪个桌面管理器? - danilo
@danilo 我怎么知道? - user3435121
@user3435121,它是Ubuntu中的一个单元吗?Mate,Cinammon在Linux Mint中?Fedora中的Gnome3?试试这个:printf 'Desktop: %s\nSession: %s\n' "$XDG_CURRENT_DESKTOP" "$GDMSESSION" - danilo
我电脑上没有KDE Plasma,你可以安装另一个窗口管理器,或尝试其他命令,比如:root.wm_attributes("-transparentcolor", 'gray')root.attributes("-alpha", 0.5)root.configure(bg='') - danilo
显示剩余3条评论

3

Linux方式 - 安装pqiv

"Linux方式"似乎是安装另一个软件包:

$ sudo apt install pqiv

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  pqiv
0 upgraded, 1 newly installed, 0 to remove and 11 not upgraded.
Need to get 34.6 kB of archives.
After this operation, 136 kB of additional disk space will be used.
Get:1 http://ca.archive.ubuntu.com/ubuntu xenial/universe amd64 pqiv amd64 2.2-1 [34.6 kB]
Fetched 34.6 kB in 0s (96.0 kB/s)
Selecting previously unselected package pqiv.
(Reading database ... 442035 files and directories currently installed.)
Preparing to unpack .../archives/pqiv_2.2-1_amd64.deb ...
Unpacking pqiv (2.2-1) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for mime-support (3.59ubuntu1) ...
Setting up pqiv (2.2-1) ...

但是,既然我已经为我的应用程序安装了xdotool和其他软件包,再安装一个又有什么关系呢?而且这会让Docker的人们很高兴:)
好消息是它只有136KB,并自动将启动画面放置在活动监视器的中心,而不是主监视器或X11屏幕的中心(在分辨率不同的三个监视器系统上看起来可能很有趣)。

调用 pqiv

从命令行开始(您可以使用 os.popen()subprocess.Popen() 在 Python 中轻松复制),只需键入:

pqiv -c -c -i m.png

这是我的 png 图像的样子:

mserve transparent splash screen.gif


关闭 pqiv

在终端中,当加载完成后,我必须发送 Control + C。在 Python 中,您需要从 ps 输出中进行 grepkill 该作业。在 Linux 中可能很简单,但对于我们的 Windows 朋友来说可能很陌生。

感谢 Super User answer


这个问题特别要求使用 tkinter 的方式,而且有人发布了适用于 Linux/Windows/MacOS 的解决方案。 - TheLizzard
@TheLizzard 在投入数小时寻找Linux/Tkinter解决方案之前,我已经花费了数小时在Linux/pqiv解决方案上。如果您有一个圆形闪屏窗口的Tkinter解决方案,我很乐意看看。 - WinEunuuchs2Unix

2
你可以这样做:window.attributes("-transparentcolor", "某种颜色")

1

如果只需要处理一张图片,可以按照以下步骤进行。

label = Label(root)
label.config(image='image.gif')
label.config(bg='systemTransparent')

这似乎允许GIF和Alpha通道在特定的macOS平台上表现出色。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接