高 DPI Tkinter 重新缩放当我 运行 它在 Spyder 和当我 运行 它直接在终端

HIGH DPI Tkinter re scaling when I run it in Spyder and when I run it direct in terminal

这可能不是什么编码问题。

我在 Tkinter 中开发了一个应用程序,它几乎包含在一个 canvas 中,我在其中加载图像 (matplots)。

当我从 Spyder 或 Jupyter notebook 运行 它时,我获得 143 DPI,而当我直接在终端 运行 它时,我获得 95 DPI。

最奇怪的是,一旦我从终端 运行 它显示它好像是一个 143 DPI 应用程序,但是当我加载图像时,应用程序决定完全调整大小,然后更改我的 DPI屏幕。所以整个事情调整大小,按钮,弹出框等等...

我可以从终端 运行 它对我来说非常重要,因为之后我会将它转换为 .exe 应用程序。

我的第一个方法是使用 tkinter 方法。winfo_fpixel() 并尝试对 DPI 进行比率计算并将其乘以应用程序中的每个维度。

后来我试图找到 python.exe 和 pythonw.exe 以更改与 HIGH DPI Scale 的兼容性。

你觉得有没有办法在不调整所有内容的情况下解决这个问题?

我想坚持认为我 100% 确定这与代码无关,因此我可能不会 post 任何编码示例。

谢谢。

obs:我用Windows10 ps: 我试着 运行 有两个屏幕的应用程序,发生的事情真的很有趣,当我在足够大的屏幕上使用它时它 运行 正常,但是当我将它滑到其他屏幕并制作任何 action/event 它会自动调整大小。

DPI 在很大程度上受 PC 分辨率设置的影响 - 特别是“比例和布局”的设置。 100% 是 96 DPI,150% 是 144 DPI。我猜这只是您的应用程序显示 95 和 143 的舍入错误。笔记本电脑往往具有更高分辨率的屏幕,因此 OEM 的默认设置为 >100%,这样您就不必眯着眼睛看您的应用程序。而典型的 1080p 显示器默认为 100% DPI。但是,当您“远程桌面”进入 PC 时,如果 DPI 和分辨率不同,Windows 可能会重新调整和拉伸 DPI 设置以匹配本地显示器。

Windows 将自动缩放大多数未使用 OS 明确设置“DPI 感知”的应用程序。这对于大多数应用程序来说通常都很好(尽管它们可能看起来“模糊”)。应用程序可以被编译为 dpi 感知,除非在某些多显示器情况下,否则不会被拉伸。对于图形应用程序尤其如此。这就是您所看到的错误往往会出现的地方。您通常可以通过右键单击 EXE,单击“属性”,然后在“兼容性”选项卡中找到设置来更改此行为:

The most weird thing is that once I run it from terminal it shows as if it was a 143 DPI application but when I load the image the app decides to resize completely and then change the DPI of my screen. So the whole thing resizes, buttons, pop up boxes and etc...

当您远程访问您的 PC 时,系统 DPI 发生了变化。应用程序可能会感到困惑 - 特别是如果它们不适应不断变化的 DPI 设置。或者更糟的是,应用程序向 Windows 注册它是 DPI 感知的,但不处理显示器换出时的极端情况 - 这实际上是当您远程进入它时发生的情况。但是,您可以使用上面的“属性”对话框和可用 API 的某种组合来覆盖此行为,以控制 dpi 感知。

我不太了解 TKinter(它使用 Python 进程还是它自己的 exe?)。如果您可以自己编译,则可以使用各种 Windows API 和清单设置来获得您想要的 DPI 行为。我在黑暗中的猜测是 TKinter( 声明自己是每个显示器的 dpi 感知的,但是有一个错误不能解释 DPI 的动态变化。这种情况的典型解决方法是重启应用程序.

您需要在以下链接中了解的所有信息:

https://docs.microsoft.com/en-us/windows/desktop/hidpi/high-dpi-desktop-application-development-on-windows

https://docs.microsoft.com/en-us/windows/desktop/api/shellscalingapi/nf-shellscalingapi-setprocessdpiawareness

https://msdn.microsoft.com/en-us/C9488338-D863-45DF-B5CB-7ED9B869A5E2

您还可以阅读我之前关于 Windows 应用中 DPI 感知的回答:

https://whosebug.com/search?q=user%3A104458+dpi

selbie的回答正确

此外,您可以使用 winapi 直接在 python 中设置 DPI 感知(这可以在 tkinter 中工作):

import ctypes, tkinter
try: # >= win 8.1
    ctypes.windll.shcore.SetProcessDpiAwareness(2)
except: # win 8.0 or less
    ctypes.windll.user32.SetProcessDPIAware()

root = tkinter.Tk()
....

MSDN doc: SetProcessDpiAwareness, MSDN doc: SetProcessDPIAware

这是,其中提到了 DPI 意识。