qtqlabelqiconhidpi

How to set fixed Icon size that scales with HiDPI in Qt


How can I set Icon size in my application so that it's still scaled when the users uses Screen Scaling?

In my application I have a QToolBar in the MainWindow that seems to use an Icon size of 24x24. I have some QToolButton which seem to get an Icon size of 20x20 by default, so I had to manually set it to 24x24 in order to have all Icons with same size, with setIconSize(QSize(24, 24));. Works fine without scaling:

enter image description here

When the Desktop has some scaling enabled, the Icons with the Fixed size don't get scaled, this looks then like this:

enter image description here

Another use case that I have is showing Icons in QLabels, there I have to specify the size when converting QIcon to QPixmap, this also doesn't scale mImageLabel->setPixmap(icon().pixmap(QSize(24, 24)));

Is there any better why then multiplying with the scale factor? How to get the scale factor?


Solution

  • It looks like setting the fixed size prevents any scaling from Qt side so we need to manually adjust the size. In my case it seems that I can get the correct scale factor by dividing the logicalDpi by 96, which is the DPI with scaling factor 1. I'm not sure if this is the best solution for all uses cases (haven't tested against MacOS for example) but fixes my use case.

    I wrote a simple class that scales all my fixed size to the correct value:

    #include <QApplication>
    #include <QDesktopWidget>    
    
    QSize ScaledSizeProvider::getScaledSize(const QSize &size)
    {
        return {static_cast<int>(size.width() * getXScaleFactor()), static_cast<int>(size.height() * getYScaleFactor())};
    }
    
    qreal ScaledSizeProvider::getXScaleFactor()
    {
        auto desktopWidget = QApplication::desktop();
        return desktopWidget->logicalDpiX() / getReferenceDpiValue();
    }
    qreal ScaledSizeProvider::getYScaleFactor()
    {
        auto desktopWidget = QApplication::desktop();
        return desktopWidget->logicalDpiY() / getReferenceDpiValue();
    }
    
    qreal ScaledSizeProvider::getReferenceDpiValue()
    {
        return 96.0;
    }
    

    And the simple fetch the correct value with:

    ScaledSizeProvider::getScaledSize(QSize(24, 24))