1
votes

I have a Qt application and I need to adapt the application (zoom-in/zoom-out) as the scaling changes from the OS in Display Settings.

I have read from Internet that:

The standard DPI settings are 100% (96 DPI), 125% (120 DPI), and 150% (144 DPI)

But, I am getting below DPI values when logged from the Qt application:

Scale - Physical DPI X - Physical DPI Y

100% - 158, 159

125% - 158, 159

150% - 79, 79

175% - 79, 79

So, as per the above values, the application text size has no difference for the 100% and 125% scale. Same behavior applies for 150% and 175%.

Below is the Qt code that I used:

    #include <QWidget>
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QWidget  widget;
    qInfo() << "Hello Qt";
    int dpiX = widget.physicalDpiX();
    int dpiY = widget.physicalDpiY();
    qInfo() << dpiX;
    qInfo() << dpiY;

Can anyone please guide? What I am trying to achieve is that the Qt application behaves (changes application size/ font size) depending on scaling set in Display Settings of the OS.

1

1 Answers

2
votes

I initially suggested using QWindow::devicePixelRatio() in this answer. However, as of Qt 5.12, this does not actually work correctly yet. Qt will avoid fractional scaling ratios due to a bug in Qt's UI scaling implementation. So for 125%, it will still return a 1.0 scaling factor. At 175%, it will return 2.0 instead of 1.75.

So for now, you should fall back to querying the DPI. However, query the logical DPI, not the physical DPI as you are doing now. Replace calls to physicalDpi() functions with calls to logicalDpi() ones. This should give you the standard 96/120/144 DPI reported by Microsoft Windows.

The previous part of the answer below can be used once Qt fixes the bug.


Previous answer, applicable once Qt fixes their scaling bug

Query the scaling ratio directly, don't try to infer it from the DPI. You use QWindow::devicePixelRatio() for this. At 100% scaling, this will return 1.0. At 125% scaling, it will return 1.25. And so on. Since this is a scaling factor, you use it as a multiplier for your sizes.

You should call devicePixelRatio() on the window your widget is currently in. This is because different windows can be on different displays on multi-monitor setups.

The window the widget is in can be obtained with QWidget::windowHandle(). This can return null if the widget is not a window. So you should probably write a small helper function that returns the correct DPR (Device Pixel Ratio) for a widget. It should take a QWidget as argument, and if windowHandle() returns null for the widget, walk up the parent tree, calling windowHandle() on each parent until it finds the first one that doesn't return null. Then return windowHandle()->devicePixelRatio(). This will be the correct DPR to use in that widget.