首页 > 解决方案 > 如何在 Windows 上测试不同 DPI/屏幕分辨率的 Qml/Quick UI?

问题描述

有人知道在 Windows 上针对不同 DPI 缩放和屏幕分辨率测试 Qml/Quick UI 的解决方案(Qt 方法/外部应用程序/等)吗?

我正在编写带有自定义 ui 元素的 android qml 应用程序,但是当在我自己的 android 手机上看起来正常时,在其他具有其他 DPI 的 android 手机上它变得非常不同。

我想使用 Android 模拟器甚至一些虚拟显示器(如 pyvirtualdisplay),但所有这些解决方案都很慢且难以使用。我正在使用 C++ 代码编写 android 应用程序,因此它不仅是用于渲染的 Qml 文件。

那么也许有人在之前在 Qt for android 上开发时已经决定了这个问题?

理想情况下,QWidget (QQuickView) 将使用一些 Qt 方法来渲染具有特定缩放的小部件内容(以模拟 DPI)。

标签: qttestingqmlscreendpi

解决方案


通过基于计算缩放比率(在 Qt 文档中)中描述的比率数学编写一些帮助代码,我已经取得了“足够好”的成功。

主要缺点是这需要您养成将任何原始文字大小数字包装在辅助函数中的习惯。

起点是如下代码,只需要在应用程序启动时执行一次:

#include <QGuiApplication>
#include <QScreen>
#include <QDebug>
...

    auto screen = QGuiApplication::primaryScreen();
    const QRect currScreen = screen->geometry();
    const qreal dpi = screen->logicalDotsPerInch();

    const double refDpi = 96;
    const double refHeight = 2160;
    const double refWidth = 3840;

    // These computations are taken nearly verbatim from:
    //   https://doc.qt.io/qt-5/scalability.html#calculating-scaling-ratio
    //   (archival) http://web.archive.org/web/20210511233243/https://doc.qt.io/qt-5/scalability.html#calculating-scaling-ratio

    m_extentsRatio = qMin( currScreen.height() / refHeight, currScreen.width() / refWidth );
    m_fontsRatio = qMin( currScreen.height() * refDpi / ( dpi * refHeight ), currScreen.width() * refDpi / ( dpi * refWidth ) );

    qDebug() << "m_extentsRatio" << m_extentsRatio;
    qDebug() << "m_fontsRatio" << m_fontsRatio;

很明显,这些变量捕获有关您正在测试的主机(例如您的笔记本电脑)的信息:

    auto screen = QGuiApplication::primaryScreen();
    const QRect currScreen = screen->geometry();
    const qreal dpi = screen->logicalDotsPerInch();

相比之下:

refDpi, refHeight, 并refWidth表示您希望“模拟”的屏幕的 {DPI,height,width}(例如某些奇特的手机型号)。

如果您想让整个方法更容易“可插入”,您可以将refDpirefHeightrefWidth作为命令行参数传递给您的应用程序,这样您就可以重新启动以模拟各种目标模型,而无需重新编译。

解决方案的其余部分是:(1)编写一个Q_INVOKABLE您的 QML 代码可以使用的辅助函数,以及(2)始终喜欢将原始文字整数大小包装在该辅助函数中。

具体来说:

    Q_INVOKABLE double asIfOnSomePhone( double input, bool isFontSize )
    {
        if( isFontSize )
        {
            return input * m_fontsRatio;
        }
        else
        {
            return input * m_extentsRatio;
        }
    }

在 QML 中:

        Layout.minimumHeight: localScreen.asIfOnSomePhone(157,
                                                          false /*isFontSize*/)
        Layout.maximumHeight: Layout.minimumHeight

        Layout.minimumWidth: localScreen.asIfOnSomePhone(625,
                                                         false /*isFontSize*/)
        Layout.maximumWidth: Layout.minimumWidth

...

  property font basicFont
  basicFont.bold: false
  basicFont.underline: false
  basicFont.pointSize: localScreen.asIfOnSomePhone(14, true /*isFontSize*/)
  basicFont.family: "Bitstream Vera Sans"


这使我能够轻松地迭代 GUI 设计,该设计旨在最终在分辨率与我在日常工作中使用的显示器大不相同的显示器上运行。一旦我开始应用这种策略,我就能够以最小的惊喜将我的设计转移到最终平台上。


我养成的另一个习惯,可以减轻在 QML 中编写响应式 UI 的一些困难,是将许多测量值表示为总显示高度和/或宽度的比例。我使用名为percentOfAppHeightCappedMinAndMaxpercentOfAppWidthCappedMinAndMax的辅助函数。您可以在 GitHub 上找到完整的工作示例


推荐阅读