[Interest] HiDPI issues

Kevin André hyperquantum at gmail.com
Sun Sep 12 19:39:39 CEST 2021


I am trying to follow the "long term" advice here:
This means that I don't set any attributes or environment variables
regarding HiDPI, and that I try to use widget sizes that are
"calculated from font metrics or screen size".

One example, a custom widget that used to have a hardcoded size. The
widget was too small on the 4K screen of my new laptop (scaling factor
in Windows set to 250%), so I changed it as follows:

QSize ColorSwitcher::minimumSizeHint() const
    auto size = desiredSize();
    return QSize(size, size);

QSize ColorSwitcher::sizeHint() const
    return minimumSizeHint();

qreal ColorSwitcher::desiredSize() const
    QFontMetricsF metrics { font() };
    return metrics.height() * 0.8;

But when I run this code, the widget is even smaller than with the
hardcoded size it used to have. Then when I move the application
window to the other monitor and back again (shift-win-arrow keys), the
size of the widget is suddenly what it should be.

The other monitor is an external screen with classic DPI (scaling
factor set to 100%) and is the primary screen. It's as if the font
metrics operate on the wrong values until I force them to refresh
somehow by moving the application window across different screens.

I am having a similar problem with a few QLabel instances. Their size
is too small for their text content. The text has the right size, but
the size of the label looks like it has been calculated for the same
text with a much lower DPI. Moving the application window to the other
screen and back again fixes the size issue here as well. Most QLabels
don't have this problem, only those two that I insert at runtime are

Just in case it is relevant, this is how I insert them:

// ClickableLabel is derived from QLabel; it uses mousePressEvent to
emit a clicked() signal
// static function, called to replace a placeholder label
ClickableLabel* ClickableLabel::replace(QLabel*& existingLabel)
    auto* clickable = new ClickableLabel();
    auto parent = existingLabel->parentWidget();
    auto layoutItem = parent->layout()->replaceWidget(existingLabel, clickable);
    delete layoutItem;
    delete existingLabel;
    existingLabel = clickable;
    return clickable;

I use the "replace" trick because it is impractical to use custom
widgets in the designer.

So am I facing a bug in Qt, or am I doing something wrong here?
My Qt version is 5.15.2.



More information about the Interest mailing list