Screeninfo Package causes DPI Awareness Error using PyQt6

762 Views Asked by At

I am trying to determine the resolution of the primary monitor within a PyQt6 application. Unfortunately, that causes the following error:
qt.qpa.window: SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: COM error 0x5: Access is denied.

Qt's default DPI awareness context is DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you are doing you can overwrite this default using qt.conf (https://doc.qt.io/qt-6/highdpi.html#configuring-windows)

While this error only shows up twice, when starting the application within VS Code, when running the application as a standalone executable created with pyinstaller, the error appears infinitely causing the application to loop. This even results in the Windows OS to lag like crazy. On top of that Windows is not able to close the application, not even through the task manager. In the end, I had to brute force the shutdown via power button.

I know that it is the screeninfo package causing the error, because removing it removes the error. However, I need to use screeninfo in order to determine the resolution of the primary monitor like so:

from screeninfo import get_monitors

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

I need the resolution to set the size of my UI Elements to take up the same relative space on every computer.

On a side note, Qt documentation says that it supports DPI aware scaling by default. However, when not using relative sizing, my application looks different on monitors with different resolution. So, how is that supposed to work?

This is my first complete application built with python btw, so I have basically no idea what I am doing..

1

There are 1 best solutions below

0
keenan On

If you want to pass screen width and height to methods, you need to get the screen's pixel size from the active QApplication. Otherwise, it won't work.

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()}")

However, if you still want to try, you can directly pass QApplication().primaryScreen()... and not the object. But, calling QApplication() will create a new QApplication object (and, if you already have one, I think that wouldn't be a good idea).