Pyglet的window.set_location()方法Windows下定位异常求助
问题描述
我在使用Pyglet库时遇到了一个异常问题:此前window.set_location(x,y)方法和窗口居中功能都正常工作,但在Windows系统上常规居中窗口时,窗口突然完全偏离中心位置。
排查过重新安装Pyglet、搜索相关案例后都没有解决问题。经过测试发现,计算出的预期窗口位置和实际显示位置存在固定的1.25倍缩放差异,实际屏幕坐标总是比计算坐标放大1.25倍。我猜测这和DPI有关,但Pyglet的DPI设置似乎只作用于文本(尤其是字体)。
想请教:这个影响屏幕定位的缩放因子是什么?它是如何生效的?有没有相关的解决办法?
测试代码如下:
import pyglet screen_w, screen_h = 1920, 1080 # Windows屏幕分辨率 window_w, window_h = 400,400 # Pyglet窗口大小 window = pyglet.window.Window(window_w, window_h) window.set_location((screen_w-window_w)//2, (screen_h-window_h)//2) # 尝试居中窗口 pyglet.app.run()
原因分析
这个1.25倍的缩放因子就是Windows系统的DPI缩放比例,对应系统设置里的125%显示缩放。
在Windows中,开启高DPI缩放后,操作系统会对窗口进行全局缩放适配,但Pyglet的window.set_location()方法默认使用的是逻辑坐标(未经过缩放的系统原始坐标),而屏幕实际的物理坐标已经被系统按DPI比例放大,这就导致了定位偏差。
Pyglet对高DPI的支持存在局限性:它的文本DPI设置仅处理字体渲染逻辑,窗口位置计算模块没有自动适配系统的DPI缩放比例,所以当系统DPI缩放为125%时,你用逻辑坐标计算的位置会被系统再次放大1.25倍,最终窗口就会偏离预期的中心位置。
解决方法
手动获取DPI缩放比例修正坐标
通过Windows API获取当前系统的DPI缩放比例,然后对计算出的居中坐标进行反向缩放,抵消系统的自动放大:
import pyglet import ctypes # 启用进程DPI感知,确保获取正确的DPI值 user32 = ctypes.windll.user32 user32.SetProcessDPIAware() # 获取系统DPI,默认DPI为96 dpi = user32.GetDpiForSystem() scale_factor = dpi / 96.0 screen_w, screen_h = 1920, 1080 # Windows屏幕逻辑分辨率 window_w, window_h = 400,400 # Pyglet窗口大小 # 计算修正后的居中坐标 pos_x = int((screen_w - window_w) // 2 / scale_factor) pos_y = int((screen_h - window_h) // 2 / scale_factor) window = pyglet.window.Window(window_w, window_h) window.set_location(pos_x, pos_y) pyglet.app.run()
启用Pyglet内置高DPI支持(1.5+版本适用)
如果你使用的是Pyglet 1.5及以上版本,可以尝试在创建窗口时添加high_dpi=True参数,让库自动处理DPI缩放适配:
window = pyglet.window.Window(window_w, window_h, high_dpi=True)
注意:该参数的效果可能受系统DPI设置影响,部分场景下可能需要结合手动坐标修正一起使用。
内容的提问来源于stack exchange,提问作者Apostolos

