tkinter无法正确识别屏幕分辨率 [英] tkinter not recognizing screen resolution correctly
问题描述
我正在使用4k显示屏(3840x2160).
I'm using a 4k display (3840x2160).
from tkinter import *
root = Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
print (width, height)
mainloop()
当我运行此代码时,输出为864的1536
When I run this code the output is 1536 by 864
有人可以解释为什么会发生这种情况,我该如何解决它,谢谢.
Could someone explain why this is happening, and how I can fix it, Thanks.
推荐答案
看着问题,这似乎是ms-windows中的缺陷,并且tk
没有使用已知的解决方法.
Looking at the problem, it seems to be a defect in ms-windows, and tk
not using the known workaround for it.
查看tk
的源代码,在文件win/tkWinX.c
中,功能TkWinDisplayChanged
使用Windows API调用GetDeviceCaps
来获取带有参数HORZRES
和VERTRES
的屏幕宽度和高度.
Looking at the source code for tk
, in the file win/tkWinX.c
the function TkWinDisplayChanged
uses the windows API call GetDeviceCaps
to get the screen width and height with the parameters HORZRES
and VERTRES
.
不幸的是,此页面状态(重点是我的):
Unfortunately, this page states (emphasis mine):
注意
GetDeviceCaps
报告显示驱动程序提供的信息. 如果显示驱动程序拒绝报告任何信息,则GetDeviceCaps
根据固定的计算来计算该信息..如果显示驱动程序报告了无效的信息,则GetDeviceCaps返回无效的信息.另外,如果显示驱动程序拒绝报告信息,则GetDeviceCaps可能会计算不正确的信息,因为它假定使用固定DPI(96 DPI)或固定大小(取决于显示驱动器提供和未提供的信息). 不幸的是,在Windows显示驱动程序模型(WDDM)中实现的显示驱动程序(在Windows Vista中引入)导致GDI无法获取信息,因此GetDeviceCaps必须始终计算信息.
Note
GetDeviceCaps
reports info that the display driver provides. If the display driver declines to report any info,GetDeviceCaps
calculates the info based on fixed calculations. If the display driver reports invalid info, GetDeviceCaps returns the invalid info. Also, if the display driver declines to report info, GetDeviceCaps might calculate incorrect info because it assumes either fixed DPI (96 DPI) or a fixed size (depending on the info that the display driver did and didn’t provide). Unfortunately, a display driver that is implemented to the Windows Display Driver Model (WDDM) (introduced in Windows Vista) causes GDI to not get the info, so GetDeviceCaps must always calculate the info.
我将其表述如下: 在Windows Vista之后,不信任来自GetDeviceCaps
的显示信息."
I would rephrase that as follows; "after windows Vista, display information from GetDeviceCaps
is not to be trusted".
这里有 real 窗口大小.
GetDeviceCaps
似乎使用的默认" DPI是96.
There there is this page about high-dpi displays.
This page uses some other GetDeviceCaps
values, LOGPIXELSX
and LOGPIXELSY
(the numbers of pixels per "logical inch" in x and y) to calculate the real window size.
The "default" DPI that GetDeviceCaps
seems to use is 96.
看看win/tkWinX.c
中的tk
代码片段,您会发现tk
使用LOGPIXELSX
和LOGPIXELSY
来计算屏幕尺寸,以mm为单位.
Look at this fragment of tk
code from win/tkWinX.c
, you can see that tk
uses LOGPIXELSX
and LOGPIXELSY
to calculate the screen size in mm.
void
TkWinDisplayChanged(
Display *display)
{
HDC dc;
Screen *screen;
if (display == NULL || display->screens == NULL) {
return;
}
screen = display->screens;
dc = GetDC(NULL);
screen->width = GetDeviceCaps(dc, HORZRES);
screen->height = GetDeviceCaps(dc, VERTRES);
screen->mwidth = MulDiv(screen->width, 254,
GetDeviceCaps(dc, LOGPIXELSX) * 10);
screen->mheight = MulDiv(screen->height, 254,
GetDeviceCaps(dc, LOGPIXELSY) * 10);
该值似乎用于计算winfo_fpixels()
所以我认为,如果您使用root.winfo_fpixels('1i')
,您将获得可靠的 DPI值.
This value seems to be used to calculate winfo_fpixels()
So I think that if you use root.winfo_fpixels('1i')
you will get a reliable DPI value.
因此,请尝试以下操作:
So, try this:
import tkinter as tk
root = tk.Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
dpi = root.winfo_fpixels('1i')
real_width = int(width * dpi / 96)
real_height = int(height * dpi / 96)
print('real width should be', real_width)
print('real height should be', real_height)
编辑,一种解决方法是设置tkinter
的缩放比例:
Edit A workaround is to set tkinter
's scaling factor:
factor = dpi / 72
root.tk.call('tk', 'scaling', factor)
这篇关于tkinter无法正确识别屏幕分辨率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!