You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使CustomTkinter窗口和Toplevel在任意分辨率与缩放比例下居中

解决CustomTkinter主窗口与Toplevel窗口在Windows缩放环境下的居中问题

Windows的DPI缩放会导致Tkinter(CustomTkinter基于此)的屏幕分辨率获取方法返回虚拟缩放值,直接用winfo_screenwidth()/winfo_height()结合窗口尺寸计算居中坐标会出现偏移。核心解决思路是先让进程启用DPI感知,确保屏幕分辨率与窗口尺寸使用统一的逻辑单位,再计算居中坐标。

实现步骤与代码示例

1. 启用DPI感知

在创建CustomTkinter窗口前,调用Windows API设置进程的DPI感知模式,确保Tkinter获取的屏幕参数与缩放比例匹配:

import ctypes
# 启用系统级DPI感知(适配全局缩放),若需多显示器不同缩放,替换为2
ctypes.windll.shcore.SetProcessDpiAwareness(1)

2. 主窗口居中实现

import customtkinter as ctk
import ctypes

# 必须在窗口创建前调用
ctypes.windll.shcore.SetProcessDpiAwareness(1)

class CenteredMainWindow(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("居中主窗口")
        self.geometry("600x400")  # 设置窗口逻辑尺寸
        self.center_window()

    def center_window(self):
        # 更新窗口任务,确保获取真实尺寸
        self.update_idletasks()
        # 获取屏幕逻辑分辨率
        screen_w = self.winfo_screenwidth()
        screen_h = self.winfo_screenheight()
        # 获取窗口逻辑尺寸
        window_w = self.winfo_width()
        window_h = self.winfo_height()
        # 计算居中坐标
        pos_x = int((screen_w - window_w) / 2)
        pos_y = int((screen_h - window_h) / 2)
        # 应用位置
        self.geometry(f"{window_w}x{window_h}+{pos_x}+{pos_y}")

if __name__ == "__main__":
    app = CenteredMainWindow()
    app.mainloop()

3. Toplevel窗口居中实现

Toplevel窗口的居中逻辑与主窗口一致,只需继承ctk.CTkToplevel并复用居中方法:

class CenteredToplevel(ctk.CTkToplevel):
    def __init__(self, parent):
        super().__init__(parent)
        self.title("居中Toplevel")
        self.geometry("400x300")
        self.center_window()

    def center_window(self):
        self.update_idletasks()
        screen_w = self.winfo_screenwidth()
        screen_h = self.winfo_screenheight()
        window_w = self.winfo_width()
        window_h = self.winfo_height()
        pos_x = int((screen_w - window_w) / 2)
        pos_y = int((screen_h - window_h) / 2)
        self.geometry(f"{window_w}x{window_h}+{pos_x}+{pos_y}")

# 在主窗口中调用示例
# app = CenteredMainWindow()
# top_win = CenteredToplevel(app)
# app.mainloop()

关键说明

  • 为什么之前的方法无效:未启用DPI感知时,winfo_screenwidth()返回的是Windows缩放后的虚拟分辨率,而窗口尺寸是逻辑像素,两者单位不匹配,导致坐标计算偏移。
  • DPI感知模式选择:
    • 1:系统DPI感知,适配全局统一缩放比例
    • 2:每显示器DPI感知,适合多显示器不同缩放比例的场景
  • update_idletasks()的作用:确保窗口完成布局计算,避免winfo_width()返回初始默认值(如1)导致计算错误。

内容的提问来源于stack exchange,提问作者Matias Riquelme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:38:36