使用TCL扩展在Tkinter中设置原生窗口样式

4 投票
2 回答
1298 浏览
提问于 2025-04-16 01:40

pythonware.com/library/tkinter/introduction/… 这里讲了一个叫做 overrideredirect 的方法,它可以去掉窗口的标题栏和边框。如果这个方法不够用,你可能需要设置原生窗口的样式。我不太确定 Tkinter 是否能让你做到这么底层的操作,如果不能的话,可以试试这个 TCL 扩展:twapi.magicsplat.com/ui.html#set_window_style。

在之前的一篇帖子里,我得到了一个回复,讲了怎么在 Tkinter 中添加一个类似下面图片的边框。我对 Tcl 和它的扩展不太熟悉。那么我该怎么做呢?我的最终目标就是在 Tkinter 窗口上得到下面这样的边框。

alt text

编辑:

我在 Windows 7 上使用了以下方法,但似乎没有改变样式。可能是缺少了什么。任何帮助都将非常感谢,这可能会很酷!

import string, win32ui, win32con
import Tkinter as tk

root = tk.Tk()

frame = win32ui.CreateWindowFromHandle(string.atoi(root.wm_frame(), 0))
frame.ModifyStyle(win32con.WS_CAPTION, 0, win32con.SWP_FRAMECHANGED)

root.mainloop()

2 个回答

2

一种解决办法是自己画边框。你可以使用 overrideredirect 这个命令来去掉所有的装饰,然后用网格、打包或放置的方法,把一个画布放到窗口里,填满整个窗口。接着,你可以在这个画布上画图或者使用位图来实现你想要的视觉效果。为了能够移动和调整窗口大小,你需要自己添加一些功能,但这并不是太难。

4

你可以通过结合使用Python的win32 api包和Tkinter来实现这个功能。你需要知道的是,Tk窗口其实是Win32窗口的客户端部分。窗口管理的交互是通过一个包装器来处理的,这个包装器是Tk窗口本身的父级。如果你有一个Tkinter窗口'w',那么你可以为这个框架创建一个PyWin32窗口,或者直接对它进行操作。你可以通过w.wm_frame()来获取框架的句柄(hwnd),然后解析返回的十六进制字符串,或者使用GetParent来获取Tk窗口的winfo_id值(不过wm_frame通常更可靠)。

import string, win32ui, win32con
from Tkinter import *
w = Tk()
frame = win32ui.CreateWindowFromHandle(string.atoi(w.wm_frame(), 0))
frame.ModifyStyle(win32con.WS_CAPTION, 0, win32con.SWP_FRAMECHANGED)

这段代码会去掉窗口的标题栏样式,并通知窗口它的框架已经被修改,这样就会强制重新计算窗口的几何形状,以便这个变化能够传递到Tk的子窗口。

编辑 --- 接下来的内容确保我们在窗口完全创建并映射到显示器后再修改窗口样式。

import string, win32ui, win32con
from Tkinter import *

def decaption(event):
    w = event.widget
    frame = win32ui.CreateWindowFromHandle(string.atoi(w.wm_frame(), 0))
    frame.ModifyStyle(win32con.WS_CAPTION, 0, win32con.SWP_FRAMECHANGED)
    w.bind("<Map>", None)

root = Tk()
root.bind("<Map>", decaption)
root.mainloop()

撰写回答