tkinter无法正确识别屏幕分辨率 [英] tkinter not recognizing screen resolution correctly

查看:721
本文介绍了tkinter无法正确识别屏幕分辨率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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来获取带有参数HORZRESVERTRES的屏幕宽度和高度.

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使用LOGPIXELSXLOGPIXELSY来计算屏幕尺寸,以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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆