Windows Python3.7下Tkinter隐藏标题栏并实现窗口边缘缩放问询
解决Tkinter隐藏标题栏后保留窗口缩放功能的方法
Tkinter完全可以实现你的需求,这里提供两种可行方案,优先推荐第一种(利用系统原生功能,更稳定简便):
方案一:通过Windows API隐藏标题栏(推荐)
使用overrideredirect(True)会让窗口脱离系统窗口管理,导致原生缩放、拖拽等功能失效。更优的方法是调用Windows API修改窗口样式,直接隐藏标题栏但保留可缩放边框,这样能复用系统自带的缩放逻辑。
完整代码
import tkinter as tk import ctypes # Windows API常量定义 GWL_STYLE = -16 WS_CAPTION = 0x00C00000 # 标题栏样式标识 WS_THICKFRAME = 0x00040000 # 可缩放边框样式标识 WS_SYSMENU = 0x00080000 # 系统右键菜单标识(可选保留) def hide_titlebar(window): # 获取窗口句柄 hwnd = ctypes.windll.user32.GetParent(window.winfo_id()) # 获取当前窗口样式 current_style = ctypes.windll.user32.GetWindowLongPtrW(hwnd, GWL_STYLE) # 移除标题栏样式,保留可缩放边框和系统菜单 new_style = current_style & ~WS_CAPTION | WS_THICKFRAME | WS_SYSMENU # 应用新样式 ctypes.windll.user32.SetWindowLongPtrW(hwnd, GWL_STYLE, new_style) # 刷新窗口生效 ctypes.windll.user32.SetWindowPos(hwnd, 0, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0004) root = tk.Tk() root.title("无标题栏可缩放窗口") root.geometry("400x300") # 执行隐藏标题栏操作 hide_titlebar(root) # 测试控件 tk.Label(root, text="拖拽窗口边缘即可缩放").pack(pady=50) root.mainloop()
说明
- 该方法仅针对Windows平台(符合你的环境),通过修改窗口的系统样式,去掉标题栏但保留可缩放边框,窗口依然受系统管理,支持原生的边缘缩放、右键移动窗口等功能。
方案二:使用overrideredirect(True)手动实现缩放
如果必须使用overrideredirect(True),可以通过绑定鼠标事件手动检测窗口边缘并实现缩放逻辑:
完整代码
import tkinter as tk class ResizableWindow(tk.Tk): def __init__(self): super().__init__() self.overrideredirect(True) self.geometry("400x300") # 绑定鼠标事件 self.bind("<Motion>", self.check_edge) self.bind("<ButtonPress-1>", self.start_resize) self.bind("<B1-Motion>", self.resize_window) # 边缘检测阈值(像素) self.edge_thresh = 10 self.resize_mode = None # 记录初始状态 self.start_x = self.start_y = 0 self.start_w = self.start_h = 0 self.start_win_x = self.start_win_y = 0 def check_edge(self, event): """检测鼠标是否在窗口边缘,切换光标样式""" w, h = self.winfo_width(), self.winfo_height() resize_mode = None cursor = "arrow" # 判断鼠标所在边缘区域 if event.x <= self.edge_thresh and event.y <= self.edge_thresh: resize_mode, cursor = "topleft", "size_nw_se" elif event.x >= w - self.edge_thresh and event.y <= self.edge_thresh: resize_mode, cursor = "topright", "size_ne_sw" elif event.x <= self.edge_thresh and event.y >= h - self.edge_thresh: resize_mode, cursor = "bottomleft", "size_ne_sw" elif event.x >= w - self.edge_thresh and event.y >= h - self.edge_thresh: resize_mode, cursor = "bottomright", "size_nw_se" elif event.x <= self.edge_thresh: resize_mode, cursor = "left", "size_we" elif event.x >= w - self.edge_thresh: resize_mode, cursor = "right", "size_we" elif event.y <= self.edge_thresh: resize_mode, cursor = "top", "size_ns" elif event.y >= h - self.edge_thresh: resize_mode, cursor = "bottom", "size_ns" self.resize_mode = resize_mode self.config(cursor=cursor) def start_resize(self, event): """记录缩放初始状态""" if self.resize_mode: self.start_x, self.start_y = event.x_root, event.y_root self.start_w, self.start_h = self.winfo_width(), self.winfo_height() self.start_win_x, self.start_win_y = self.winfo_x(), self.winfo_y() def resize_window(self, event): """根据边缘模式调整窗口大小""" if not self.resize_mode: return dx = event.x_root - self.start_x dy = event.y_root - self.start_y min_size = 100 # 窗口最小尺寸限制 match self.resize_mode: case "right": new_w = max(min_size, self.start_w + dx) self.geometry(f"{new_w}x{self.start_h}") case "left": new_w = max(min_size, self.start_w - dx) self.geometry(f"{new_w}x{self.start_h}+{self.start_win_x + dx}+{self.start_win_y}") case "bottom": new_h = max(min_size, self.start_h + dy) self.geometry(f"{self.start_w}x{new_h}") case "top": new_h = max(min_size, self.start_h - dy) self.geometry(f"{self.start_w}x{new_h}+{self.start_win_x}+{self.start_win_y + dy}") case "bottomright": new_w = max(min_size, self.start_w + dx) new_h = max(min_size, self.start_h + dy) self.geometry(f"{new_w}x{new_h}") case "topleft": new_w = max(min_size, self.start_w - dx) new_h = max(min_size, self.start_h - dy) self.geometry(f"{new_w}x{new_h}+{self.start_win_x + dx}+{self.start_win_y + dy}") case "topright": new_w = max(min_size, self.start_w + dx) new_h = max(min_size, self.start_h - dy) self.geometry(f"{new_w}x{new_h}+{self.start_win_x}+{self.start_win_y + dy}") case "bottomleft": new_w = max(min_size, self.start_w - dx) new_h = max(min_size, self.start_h + dy) self.geometry(f"{new_w}x{new_h}+{self.start_win_x + dx}+{self.start_win_y}") if __name__ == "__main__": app = ResizableWindow() tk.Label(app, text="拖拽窗口边缘缩放").pack(pady=50) app.mainloop()
说明
- 通过
<Motion>事件实时检测鼠标位置,判断是否处于窗口边缘(阈值设为10像素),切换对应光标提示; - 按下鼠标时记录初始位置和窗口尺寸,拖拽时根据边缘模式调整窗口大小和位置,同时限制最小尺寸避免窗口过小。
内容的提问来源于stack exchange,提问作者Danhui Xu
相关产品推荐
相关产品推荐

