Qt High DPI解决方案

1.不完美的方案

  • 使用Qt:AA_EnableHighDpiScaling。100%和125%程序没缩放,150%程序会变大两倍,不符合预期。
  • 使用PROCESS_DPI_UNAWARE。程序确实按照DPI缩放了,但是画面变模糊了。

2.完美的方案

一个完美的方案,必须是程序的尺寸能和DPI对应上,而且画面不模糊。

2.1 注意点

如果你的程序是结合OpenGL程序的,你需要小心,如果OpenGL是在Qt程序里面写的话,可能不会有太大的问题,但是如果OpenGL功能是由别人提供的,像自己封装成一个库,那么意味着你可能需要在一些方面要乘以那个缩放倍数,才能得到正确的OpenGL窗体大小和显示位置。多做一些测试来验证下是否存在这样的问题。

2.2 方案一

将你的Qt版本升级到Qt 6.3以上, Qt 6对于DPI有了很好的改善,如果是windows平台,你不需要做额外的动作,要做的就是看项目在Qt 6能不能成功编译。如果无法改变Qt版本,或者使用Qt 6编译不过,可以尝试下面的方法。

2.3 方案二

这个方案是针对windows的,当然Linux和Mac也是一样的思路,本质就是要得到缩放的倍数,然后设置环境变量。支持的版本应该是>= Qt 5.6,如果我没记错的话,支持QT_SCALE_FACTOR就行。

  • step1:计算缩放倍数。
  • step2:使用QT_SCALE_FACTOR,设置这个环境变化,程序会根据设置的值放大或缩小,可以是小数。
#include "mainwindow.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 

double calculateScaleFactor()
{
    auto activeWindow = GetActiveWindow();
    HMONITOR monitor = MonitorFromWindow(activeWindow, MONITOR_DEFAULTTONEAREST);

    // Get the logical width and height of the monitor
    MONITORINFOEX monitorInfoEx;
    monitorInfoEx.cbSize = sizeof(monitorInfoEx);
    GetMonitorInfo(monitor, &monitorInfoEx);
    auto cxLogical = monitorInfoEx.rcMonitor.right - monitorInfoEx.rcMonitor.left;
    auto cyLogical = monitorInfoEx.rcMonitor.bottom - monitorInfoEx.rcMonitor.top;

    // Get the physical width and height of the monitor
    DEVMODE devMode;
    devMode.dmSize = sizeof(devMode);
    devMode.dmDriverExtra = 0;
    EnumDisplaySettings(monitorInfoEx.szDevice, ENUM_CURRENT_SETTINGS, &devMode);
    auto cxPhysical = devMode.dmPelsWidth;
    auto cyPhysical = devMode.dmPelsHeight;

    // Calculate the scaling factor
    double horizontalScale = ((double)cxPhysical / (double)cxLogical);
    double verticalScale = ((double)cyPhysical / (double)cyLogical);

    std::cout << "Horizonzal scaling: " << horizontalScale << "\n";
    std::cout << "Vertical scaling: " << verticalScale;

    return horizontalScale > verticalScale ? verticalScale : horizontalScale;
}


int main(int argc, char *argv[])
{
    double scaleFactor = calculateScaleFactor();
    // enable QIcon produces highdpi pixmap
    QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);

    qputenv("QT_SCALE_FACTOR", QByteArray::number(scaleFactor));

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

3.额外的信息

为了更好的支持DPI,我们应该在项目使用矢量图,比如svg图片,这样可以确保我们在任何DPI都能显示正确,而且不模糊。我们使用AA_UseHighDpiPixmaps和QIcon的结合的方式,来获取正确的缩放的图片。下面是一些我对svg图片测试的总结

3.1 svg图片测试总结

  • 如果你使用svg图片来设置StyleSheet,这个属性是不受AA_UseHighDpiPixmaps的影响的,而且应该使用image会显示正确,border-image和background-image显示都是错误的。
  • 在你整个程序,用到字体的时候,都应该使用点大小。
  • 你在使用QPixmap的时候,是使用QIcon返回的QPixmap,而不是直接使用QPixmap,用QPainter画QPixmap也是一样的道理。必须确保Qt::AA_UseHighDpiPixmaps属性有使用。

4. 结果

Qt High DPI解决方案_第1张图片
完整代码github

你可能感兴趣的:(Qt,qt,c++,high,dpi,dpi)