Qt获取屏幕DPI缩放比

获取屏幕缩放比

网上很多代码是用 logicalDotsPerInch 除以 96 来获取屏幕缩放比:

// Windows 除以 96,macOS 除以 72
qreal factor = window->screen()->logicalDotsPerInch() / 96.0;

当使能了缩放适配后,logicalDotsPerInch 值就不随系统缩放变了:

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    // Qt6 默认开启缩放
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif

如果是 PassThrough 支持小数的设置,此时可以用 QScreen 的 devicePixelRatio 获取缩放比。

很明显,我们需要更通用的方式。通过查看源码,发现其实 Qt 内部是有对应接口的,比如 QHighDpiScaling 类的接口:

qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen)
{
    // Determine if physical DPI should be used
    static const bool usePhysicalDpi = qEnvironmentVariableAsBool(usePhysicalDpiEnvVar, false);

    // Calculate scale factor beased on platform screen DPI values
    qreal factor;
    QDpi platformBaseDpi = screen->logicalBaseDpi();
    if (usePhysicalDpi) {
        QSize sz = screen->geometry().size();
        QSizeF psz = screen->physicalSize();
        qreal platformPhysicalDpi = ((sz.height() / psz.height()) + (sz.width() / psz.width())) * qreal(25.4 * 0.5);
        factor = qreal(platformPhysicalDpi) / qreal(platformBaseDpi.first);
    } else {
        const QDpi platformLogicalDpi = QPlatformScreen::overrideDpi(screen->logicalDpi());
        factor = qreal(platformLogicalDpi.first) / qreal(platformBaseDpi.first);
    }

    return factor;
}

其中  usePhysicalDpi 一般我们也用不到,所以可以直接用 else 部分的逻辑。不过这里用到了 QPlatformScreen 类,需要引入 gui-private 模块:

QT += core gui widgets 
QT += gui-private

简单的测试:

void MainWindow::calcDpi()
{
    // 可以从 QWidget 或者 QWindow 拿到 QScreen 对象
    QScreen *cur_screen = this->screen();
    qDebug()<<__FUNCTION__<<cur_screen;
    if (cur_screen) {
        // 逻辑 dpi (logicalBaseDpi().first) 默认值 win 96/ mac 72
        const QDpi base_dpi = cur_screen->handle()->logicalBaseDpi();
        const QDpi logic_dpi = QPlatformScreen::overrideDpi(cur_screen->handle()->logicalDpi());
        // 得到屏幕缩放百分比
        const qreal factor = qreal(logic_dpi.first) / qreal(base_dpi.first);
        qDebug()<<"calc dpi"<<factor;
    }
}

关联屏幕设置变化

当在多个屏幕拖动,或者修改当前屏幕缩放比后,我们需要重新获取缩放比。

QWindow 提供了 screenChanged 信号可以感知屏幕切换。

QScreen 提供了 physicalDotsPerInchChanged 和 logicalDotsPerInchChanged 信号可以感知分辨率变化。

在 Widgets 中的大致代码就是:

void MainWindow::initWindow()
{
    qDebug()<<this->winId();
    // 构造的时候 windowHandle 还未初始化,可以等 show 的时候关联,或者先调用一次 winId
    connect(this->windowHandle(), &QWindow::screenChanged, this, &MainWindow::onScreenChange);
    calcDpi();
}

void MainWindow::onScreenChange(QScreen *screen)
{
    // QMetaObject::Connection 保存连接便于释放;
    if (logicalDpiConnection) {
        disconnect(physicalDpiConnection);
        disconnect(logicalDpiConnection);
    }
    if (screen) {
        // 切换缩放比时,EnableHighDpiScaling 会触发 physicalDotsPerInchChanged
        // 此时 Qt6 不触发 logicalDotsPerInchChanged
        physicalDpiConnection = connect(screen, &QScreen::physicalDotsPerInchChanged, this, &MainWindow::calcDpi);
        logicalDpiConnection = connect(screen, &QScreen::logicalDotsPerInchChanged, this, &MainWindow::calcDpi);
        calcDpi();
    }
}

void MainWindow::calcDpi()
{
    // 可以从 QWidget 或者 QWindow 拿到 QScreen 对象
    QScreen *cur_screen = this->screen();
    qDebug()<<__FUNCTION__;
    if (cur_screen) {
        // 逻辑 dpi (logicalBaseDpi().first) 默认值 win 96/ mac 72
        const QDpi base_dpi = cur_screen->handle()->logicalBaseDpi();
        const QDpi logic_dpi = QPlatformScreen::overrideDpi(cur_screen->handle()->logicalDpi());
        // 得到屏幕缩放百分比
        const qreal factor = qreal(logic_dpi.first) / qreal(base_dpi.first);
        qDebug()<<"calc dpi"<<factor;
    }
}

完成示例代码:

QWidget 获取 DPI 缩放:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/TestQt_20231221_Dpi

QML 获取 DPI 缩放:

https://github.com/gongjianbo/MyTestCode/tree/master/Qml/TestQml_20231221_Dpi

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Qt是一个跨平台的GUI库,常用于开发桌面应用程序。在多屏环境下,Qt可以很好地支持屏幕缩放比例。 对于多屏环境,Qt提供了一种简单的方法来访问所有屏幕,并且多个屏幕可以在Qt中作为一个具有单一逻辑大小的桌面表现。Qt 5中提供了两种方法来实现屏幕缩放比例DPI缩放和UI缩放DPI缩放是指Qt通过重新计算每个屏幕上的像素密度来适应不同的屏幕,从而使应用程序在多屏幕上保持屏幕分辨率一致。UI缩放是指Qt可以通过缩放UI控件来适应不同的屏幕分辨率,这样就可以缩放应用程序的整个UI界面。 无论是DPI缩放还是UI缩放,都需要对应用程序进行一些调整,并且需要考虑到每个屏幕的分辨率和大小。Qt提供了一些函数和类来优化多屏环境下的应用程序,如QScreen和QWindow等。 综上所述,Qt提供了多种方法来适应多屏幕环境,其中包括DPI缩放和UI缩放。开发人员应该根据具体情况选择合适的缩放方法,并且对应用程序进行必要的调整,以确保在多屏幕环境下有更好的用户体验。 ### 回答2: 在使用Qt多屏开发时,我们可能需要考虑到不同的屏幕分辨率和缩放比例对UI界面的影响,以保证程序在不同设备上具有良好的用户体验。 首先,Qt提供了一些关于屏幕分辨率和缩放比例的接口函数,比如QScreen::availableSize()和QScreen::logicalDotsPerInch()。这些函数可以帮助我们获取当前屏幕的大小和密度信息。同时,Qt还提供了一些函数来响应屏幕缩放比例的变化,比如QWindow::devicePixelRatioChanged()和QWidget::resizeEvent()。 其次,为了适应不同的分辨率和缩放比例,我们需要采取一些措施来调整UI界面的布局和大小。例如,我们可以使用Qt的布局管理器来自动计算和调整界面控件的大小和位置,以适应不同的屏幕分辨率。另外,我们还可以考虑使用矢量图形代替位图图像,以保证图像在不同分辨率下的清晰度。 最后,我们需要进行充分的测试和调试,以确保程序在不同屏幕分辨率和缩放比例下的表现都符合预期。这个过程既可以手动进行,也可以借助一些自动化测试工具来完成。 综上所述,Qt多屏开发需要考虑到不同的屏幕分辨率和缩放比例,采取相应的措施来调整UI界面的布局和大小,并进行充分的测试和调试。 ### 回答3: Qt 是一个跨平台的 C++ 应用程序开发框架,旨在为开发者提供高效且易于使用的工具来创建现代 UI 界面和应用程序。在 Qt 中,多屏和屏幕缩放比例都是需要注意的重要问题。 Qt 通过 QScreen 类提供了多屏支持。通过检索当前系统中的所有屏幕,并使用 QDesktopWidget 类的基本辅助函数计算其大小和位置,您可以获取要素,如应用程序是否覆盖多个屏幕等。在QScreen中,可以通过geometry()和availableGeometry() 函数获取屏幕的宽高和可用宽高。 对于屏幕缩放比例Qt 允许您在不同的设备上为不同的密度设置缩放比例DPI (Dots Per Inch) 是测量显示器分辨率的单位,通常用于确定屏幕上图像和文本的大小。在 Qt 中,可以使用QScreen::devicePixelRatio()获取屏幕缩放比例。如果您想将您的应用程序设计为在不同分辨率和设备上都能正常显示,您需要根据屏幕的实际 DPI 设置计算缩放比例。在 Qt 中,可以使用QApplication::primaryScreen()->logicalDotsPerInch()获取当前屏幕DPI 值,然后根据需要采用不同的缩放比例来设置应用程序。 在 Qt 中,多屏和屏幕缩放比例都需要仔细考虑,以确保您的应用程序在不同的设备和分辨率上都能正常显示,并为最终用户提供出色的体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚建波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值