已设置最大最小尺寸的Tkinter窗口拖到屏幕顶部时仍会扩张如何解决?
解决方案
问题根源
这个问题是Windows系统高DPI缩放+窗口停靠(Aero Snap)机制共同导致的:
- 你的笔记本开启150%系统缩放,1920物理宽度的屏幕对应的逻辑像素宽度为
1920 / 1.5 = 1280px - 你设置的窗口最大宽度为1270px,拖动窗口到顶部触发Windows自动停靠时,系统会强制将窗口宽度拉满到屏幕逻辑宽度1280px,多出来的10px就显示为窗口默认的浅灰色背景
- 大尺寸显示器逻辑宽度远大于1270px,触发停靠时不会超过你设置的maxsize,因此没有异常
修复步骤
1. 开启Tkinter高DPI感知(Windows平台)
首先让Tkinter适配系统缩放,避免像素单位计算偏差,这部分代码需要放在创建Tk窗口之前执行,同时做系统判断避免跨平台报错。
2. 监听窗口尺寸变化强制固定大小
监听窗口的<Configure>事件,只要窗口尺寸超出你设定的1270x725,就立刻强制重置为目标尺寸,从根源上避免系统自动拉伸。
3. 优化canvas布局(可选)
把原来的相对定位改为固定偏移,避免窗口尺寸波动时canvas位置偏移。
完整修复后代码
import sys from tkinter import * # Windows平台开启高DPI感知 if sys.platform == "win32": import ctypes ctypes.windll.shcore.SetProcessDpiAwareness(1) win = Tk() TARGET_WIDTH = 1270 TARGET_HEIGHT = 725 win.geometry(f"{TARGET_WIDTH}x{TARGET_HEIGHT}+0+0") canvas1 = Canvas(win, width=1400, height=TARGET_HEIGHT, bg='#00538f') # 固定偏移130px,替代原来的相对定位,适配1270宽度的窗口 canvas1.place(x=-130, y=0) # 原有的渐变矩形绘制代码 canvas1.create_rectangle(0, 0, 1400, 72.5, fill='#005FB9', outline='#005EB9') canvas1.create_rectangle(0, 72.5, 1400, 150.4, fill='#005FC8', outline='#005FC9') canvas1.create_rectangle(0, 150.4, 1400, 217.5, fill='#005FD7', outline='#005FD9') canvas1.create_rectangle(0, 217.5, 1400, 290, fill='#005FE6', outline='#005FE9') canvas1.create_rectangle(0, 290, 1400, 362.5, fill='#005FF5', outline='#005FF9') canvas1.create_rectangle(0, 362.5, 1400, 435, fill='#005FF4', outline='#005FF9') canvas1.create_rectangle(0, 435, 1400, 507.5, fill='#005FE3', outline='#005FE9') canvas1.create_rectangle(0, 507.5, 1400, 580, fill='#005FD2', outline='#005FD9') canvas1.create_rectangle(0, 580, 1400, 652.5, fill='#005FC1', outline='#005FC9') canvas1.create_rectangle(0, 652.5, 1400, 725, fill='#005FB0', outline='#005FB9') win.minsize(width=TARGET_WIDTH, height=TARGET_HEIGHT) win.maxsize(width=TARGET_WIDTH, height=TARGET_HEIGHT) # 强制固定窗口尺寸的事件监听 def force_fixed_size(event): if win.winfo_width() != TARGET_WIDTH or win.winfo_height() != TARGET_HEIGHT: win.geometry(f"{TARGET_WIDTH}x{TARGET_HEIGHT}") win.bind("<Configure>", force_fixed_size) win.mainloop()
可选替代方案
如果你不需要保留最大化按钮的可用性,也可以直接禁用Windows的窗口停靠拉伸:
win.resizable(0,0) # 恢复最大化按钮为可点击状态(Windows平台) if sys.platform == "win32": hWnd = ctypes.windll.user32.GetParent(win.winfo_id()) GWL_STYLE = -16 WS_MAXIMIZEBOX = 0x00010000 style = ctypes.windll.user32.GetWindowLongW(hWnd, GWL_STYLE) ctypes.windll.user32.SetWindowLongW(hWnd, GWL_STYLE, style | WS_MAXIMIZEBOX)
内容的提问来源于stack exchange,提问作者neo_codex
相关产品推荐
相关产品推荐

