如何在 Windows 上测试不同 DPI/屏幕分辨率的 Qml/Quick UI?

Posted

技术标签:

【中文标题】如何在 Windows 上测试不同 DPI/屏幕分辨率的 Qml/Quick UI?【英文标题】:How test Qml/Quick UI on different DPI / screen resolution on the Windows? 【发布时间】:2019-08-26 19:38:19 【问题描述】:

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

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

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

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

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

【问题讨论】:

你启用QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling)了吗? 当然,它只是决定高dpi显示器上的字体大小,而不是DPI和分辨率不同时的缩放和比例。 好的,那么您想要实现的是在不使用模拟器或物理设备的情况下测试您的应用在手机上的外观? 是的,只是在 Windows 上测试 QML UI 的不同 DPI/分辨率。 【参考方案1】:

通过根据Calculating Scaling Ratio(在 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();

相比之下:

refDpirefHeightrefWidth 代表您希望“模拟”的屏幕的 DPI,height,width(例如某些奇特的手机型号)。

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

解决方案的其余部分是:(1) 编写一个您的 QML 代码可以使用的 Q_INVOKABLE 辅助函数,以及 (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 时遇到的一些困难,那就是将许多测量值表示为总显示高度和/或宽度的比例。我使用名为 percentOfAppHeightCappedMinAndMax 和 percentOfAppWidthCappedMinAndMax 的辅助函数。您可以找到完整的working sample on GitHub。

【讨论】:

以上是关于如何在 Windows 上测试不同 DPI/屏幕分辨率的 Qml/Quick UI?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 emf 文件 dpi 感知

W8.1 UWP / Xaml WebView 在高 DPI 屏幕上呈现较小

Android平板上开发应用的一点心得——精确适配不同的dpi和屏幕尺寸

安卓系统,5.5寸手机屏幕最合适的DPI是多少?

JDK/Java在屏幕缩放时Toolkit.getScreenResolution()的结果

鼠标参数以及选购DPI和报告率