Screeninfo 包使用 PyQt6 导致 DPI 感知错误

Screeninfo Package causes DPI Awareness Error using PyQt6

提问人:MasterOfDesaster42 提问时间:9/26/2023 更新时间:11/3/2023 访问量:182

问:

我正在尝试确定 PyQt6 应用程序中主监视器的分辨率。不幸的是,这会导致以下错误:qt.qpa.window:
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) 失败:COM 错误 0x5:访问被拒绝。

Qt的默认DPI感知上下文为DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2。如果你知道你在做什么,你可以使用 qt.conf (https://doc.qt.io/qt-6/highdpi.html#configuring-windows 覆盖这个默认值)

虽然此错误仅显示两次,但在 VS Code 中启动应用程序时,当将应用程序作为使用 pyinstaller 创建的独立可执行文件运行时,该错误会无限出现,导致应用程序循环。这甚至导致 Windows 操作系统疯狂滞后。最重要的是,Windows无法关闭应用程序,甚至无法通过任务管理器关闭。最后,我不得不通过电源按钮强行关机。

我知道是 screeninfo 包导致了错误,因为删除它会删除错误。但是,我需要使用 screeninfo 来确定主显示器的分辨率,如下所示:

from screeninfo import get_monitors

monitors = get_monitors()
for monitor in monitors:
    if monitor.is_primary:
        primary_monitor = monitor
        break

我需要分辨率来设置我的 UI 元素的大小,以便在每台计算机上占用相同的相对空间。

顺便说一句,Qt文档说它默认支持DPI感知缩放。但是,当不使用相对大小调整时,我的应用程序在具有不同分辨率的显示器上看起来会有所不同。那么,这应该如何运作呢?

顺便说一句,这是我第一个用python构建的完整应用程序,所以我基本上不知道我在做什么。

python 缩放 dpi pyqt6

评论

0赞 musicamante 9/26/2023
Qt已经提供了QScreen API来查询可用的屏幕,所以你应该使用它。请注意,这不应该是你的 UI 的基础,而且这个要求可能只是由糟糕的布局管理(你正在使用布局管理器,不是吗?)或不正确的大小设置引起的。
0赞 MasterOfDesaster42 9/26/2023
没错,我首先使用QScreens,但似乎不可能找到像这样由无线显示创建的虚拟显示器。不,我实际上没有使用布局管理器,我觉得没有它们我有更多的控制权。这是个错误吗?
0赞 musicamante 9/26/2023
您完全确定QScreen问题吗?请注意,在某些情况下,您可能需要检查 ;尽管如此,它可能是一个问题或错误,您应该考虑对该主题进行一些研究(可能通过在此处创建问题,甚至在彻底测试后报告错误)。而且,是的,不使用布局管理器几乎总是一个错误;普遍的感觉是它们难以使用,不能按预期工作,对所需的布局的控制有限,并提供有限的自定义。QApplication.screens()
0赞 musicamante 9/26/2023
在99.9%的情况下,这些都是由于经验有限和缺乏对实现正确布局所需的所有方面的了解而导致的假设,这是Qt已经彻底实现的。事实上,在极少数情况下,避免布局被认为是可以接受的(甚至是必需的),这是在充分意识到其含义并考虑现有替代方案之后做出的选择。实际上,UI 所需的功能几乎总是可以通过正确使用小部件和布局功能来实现的,例如大小提示、大小策略、间隔项和拉伸因子。
0赞 musicamante 9/26/2023
我建议你对所有这些方面进行更彻底的研究(包括正确理解Qt布局的工作原理,从基本的QLayout和QLayoutItem类开始),如果你仍然无法实现你真正想要的,那么在这里发布一个问题,并给出一个适当的最小可重复的例子,解释这个问题,并可能显示想要的结果的图像(甚至是模型)。我非常确定可以找到一个基于布局的解决方案,而不是依赖武断的假设,同时可能低估您可能没有意识到的重要方面。

答:

0赞 keenan 11/3/2023 #1

如果要将屏幕宽度和高度传递给方法,则需要从活动 .否则,它将无法正常工作。QApplication

from PySide6.QtWidgets import QApplication
import sys

app = QApplication(sys.argv)
print(f"Width: {app.primaryScreen().size().width()}")
print(f"Height: {app.primaryScreen().size().height()}")

但是,如果还是想尝试,可以直接传递而不是对象。但是,调用会创建一个新对象(如果你已经有一个对象,我认为这不是一个好主意)。QApplication().primaryScreen()...QApplication()QApplication