我可以更改Tkinter的标题栏吗?
我在用Tkinter做程序的图形界面,但我发现很多程序的界面看起来和Tkinter的标准样式不一样。这里说的标准样式指的是那种常见的标题栏、边框等等。
比如,Tkinter的标题栏是这样的:
而GitHub的标题栏则是这样的:
你看,它们有自己定制的关闭、调整大小和最小化按钮,对吧?那么,使用Tkinter能做到这样的界面吗?
提前谢谢你们!:)
11 个回答
1
在python3.5.2中,我需要做一些修改才能让这个正常工作:
#custom title bar for tkinter
from tkinter import Tk, Frame, Button, Canvas
root = Tk()
def move_window(event):
root.geometry('+{0}+{1}'.format(event.x_root, event.y_root))
root.overrideredirect(True) # turns off title bar, geometry
root.geometry('400x100+200+200') # set new geometry
# make a frame for the title bar
title_bar = Frame(root, bg='white', relief='raised', bd=2)
# put a close button on the title bar
close_button = Button(title_bar, text='Close this Window', command=root.destroy)
# a canvas for the main area of the window
window = Canvas(root, bg='black')
# pack the widgets
title_bar.pack(expand=1, fill="x")
close_button.pack(side="right")
window.pack(expand=1, fill="both")
# bind title bar motion to the move window function
title_bar.bind('<B1-Motion>', move_window)
root.mainloop()
2
这是我用 Python 3.7.2 做的一些修改
from tkinter import *
root = Tk()
root.overrideredirect(True) # turns off title bar, geometry
root.geometry('400x100+200+200') # set new geometry
# make a frame for the title bar
title_bar = Frame(root, bg='#2e2e2e', relief='raised', bd=2,highlightthickness=0)
# put a close button on the title bar
close_button = Button(title_bar, text='X', command= root.destroy,bg = "#2e2e2e",padx = 2,pady = 2,activebackground='red',bd = 0,font="bold",fg='white',highlightthickness=0)
# a canvas for the main area of the window
window = Canvas(root, bg='#2e2e2e',highlightthickness=0)
# pack the widgets
title_bar.pack(expand=1, fill=X)
close_button.pack(side=RIGHT)
window.pack(expand=1, fill=BOTH)
xwin=None
ywin=None
# bind title bar motion to the move window function
def move_window(event):
root.geometry('+{0}+{1}'.format(event.x_root, event.y_root))
def change_on_hovering(event):
global close_button
close_button['bg']='red'
def return_to_normalstate(event):
global close_button
close_button['bg']='#2e2e2e'
title_bar.bind('<B1-Motion>', move_window)
close_button.bind('<Enter>',change_on_hovering)
close_button.bind('<Leave>',return_to_normalstate)
root.mainloop()
解释:
我们把按钮的边框厚度设置为 0,这样就去掉了按钮的边框。
接着,我们把<Enter>
事件绑定到一个函数,这个函数会改变按钮的前景颜色。
为了让按钮回到原来的状态,我们又把<Leave>
事件绑定到另一个函数。
注意:光标不可见是因为我的屏幕录制软件不知怎么把它去掉了
9
我找到了一种方法,可以让标题栏变成黑色,这个方法只适用于Windows 11。
这是一个使用Tkinter的黑色标题栏示例:
import ctypes as ct
def dark_title_bar(window):
"""
MORE INFO:
https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
"""
window.update()
DWMWA_USE_IMMERSIVE_DARK_MODE = 20
set_window_attribute = ct.windll.dwmapi.DwmSetWindowAttribute
get_parent = ct.windll.user32.GetParent
hwnd = get_parent(window.winfo_id())
rendering_policy = DWMWA_USE_IMMERSIVE_DARK_MODE
value = 2
value = ct.c_int(value)
set_window_attribute(hwnd, rendering_policy, ct.byref(value),
ct.sizeof(value))
我几乎花了一年的时间在寻找这个解决方案!
10
大多数人都知道在使用上面提到的 'move_window' 方法时会出现错误;我找到了一种解决办法,它是获取鼠标的确切位置,然后根据这个位置来移动窗口,而不是从窗口的角落开始移动:
def get_pos(event):
xwin = app.winfo_x()
ywin = app.winfo_y()
startx = event.x_root
starty = event.y_root
ywin = ywin - starty
xwin = xwin - startx
def move_window(event):
app.geometry("400x400" + '+{0}+{1}'.format(event.x_root + xwin, event.y_root + ywin))
startx = event.x_root
starty = event.y_root
app.TopFrame.bind('<B1-Motion>', move_window)
app.TopFrame.bind('<Button-1>', get_pos)
28
是的,这是可能的。你可以在主窗口上使用 overrideredirect()
这个方法,这样就可以去掉标题栏和默认的窗口大小设置。之后,你需要从头开始重新设置这些功能,按照你想要的样子来调整窗口。下面是一个简单的示例,功能很基础:
root = Tk()
def move_window(event):
root.geometry('+{0}+{1}'.format(event.x_root, event.y_root))
root.overrideredirect(True) # turns off title bar, geometry
root.geometry('400x100+200+200') # set new geometry
# make a frame for the title bar
title_bar = Frame(root, bg='white', relief='raised', bd=2)
# put a close button on the title bar
close_button = Button(title_bar, text='X', command=root.destroy)
# a canvas for the main area of the window
window = Canvas(root, bg='black')
# pack the widgets
title_bar.pack(expand=1, fill=X)
close_button.pack(side=RIGHT)
window.pack(expand=1, fill=BOTH)
# bind title bar motion to the move window function
title_bar.bind('<B1-Motion>', move_window)
root.mainloop()