QML和Qt Quick最佳实践

尽管QML和Qt Quick提供很多优点,但在某些情况下可能会很具挑战性。以下部分详细介绍了如何通过实施一些最佳实践来获得更好的应用开发结果。

自定义UI控件

流畅现代的用户界面对于任何应用在当今世界的成功至关重要,这正是QML对于设计师或开发者有意义的地方。Qt提供了创建流畅现代界面所必需的最基本的UI控件。建议在创建自己的自定义UI控件之前浏览此列表中的UI控件。

除了Qt Quick本身提供的基本UI控件之外,Qt Quick Controls还提供了一套丰富的UI控件。它们直接响应最常见的使用场景,并通过其自定义选项提供了更多可能性。特别是,Qt Quick Controls提供了符合最新UI设计趋势的样式选项。如果这些UI控件无法满足您应用的需要,那么建议创建一个自定义控件。

您可以在Qt Design Studio中设计UI时使用控件。此外,它还提供基于时间线的动画、视觉效果、布局以及实时预览,用于原型设计应用。

编码约定

参见QML编码约定

打包应用程序资源

大多数应用程序都依赖于图像和图标等资源来提供丰富的用户体验。在不同操作系统之间使这些资源可用于应用程序可能是一个挑战。大多数流行的操作系统都采用更严格的安全策略,限制了对文件系统的访问,这使得加载这些资源更加困难。作为替代方案,Qt提供了自己的资源系统,这个系统被内置于应用二进制文件中,使得无论目标操作系统如何,都能访问应用程序的资源。

例如,考虑以下项目目录结构

MyModule
├── images
│   ├── image1.png
│   └── image2.png
├── CMakeLists.txt
└── main.qml

您可以使用以下方式将其表示为CMake QML模块

qt_add_qml_module(my_module
   URI MyModule
   VERSION 1.0
   QML_FILES
       main.qml
   RESOURCES
       images/image1.png
       images/image2.png
   # ...
)

以下列表中的所有QML文件都将自动进行编译

您应该将QML文件与具有qt_add_qml_module的CMakeLists.txt放在同一目录中。否则它们隐式导入将与它们所属的QML模块不同。这是经常出现错误的地方。

将用户界面与业务逻辑分离

大多数应用开发者希望实现的一个重要目标是创建一个可维护的应用程序。实现这一目标的一种方法是将用户界面与业务逻辑分离。以下是一些理由说明为什么应用程序的UI应该用QML编写

  • 声明式语言非常适合定义UI。
  • 由于QML代码比C++简洁,且不是强类型,因此更容易编写。这使得它成为原型电路的绝佳语言,当与设计师合作时,这一点至关重要。
  • JavaScript可以轻松地在QML中用于处理事件。

作为一种强类型语言,C++最适合应用程序的业务逻辑。通常,此类代码执行的任务如复杂计算或数据处理,在C++中比QML更快。

Qt为在应用程序中集成QML和C++代码提供了多种方法。一个典型的用例是在用户界面中显示数据列表。如果是静态、简单且/或小的数据集,则可以直接写出 sufficient 模型。

以下是一些用QML编写的模型示例

model: [ "Item 1", "Item 2", "Item 3" ]

model: 10

对于大型或经常修改的动态数据集,请使用C++

从C++到QML暴露数据

重构QML比重构C++容易得多,因此为了使维护无痛苦,我们应该尽可能让C++类型对QML不知情。这可以通过将C++类型的引用“推”入QML来实现。

这可以通过使用所需的属性并通过QQmlApplicationEngine::setInitialProperties设置它们来实现。还可以创建一个或多个单一实例,这将返回C++方面希望提供给QML的所有数据。

采用这种方法,即使QML在未来需要重构,C++代码也不会改变。

有关如何正确选择将C++类型暴露给QML的方法的快速指南,请参阅在选择C++和QML之间的正确集成方法

使用Qt Design Studio

Qt Design Studio使用具有文件扩展名.ui.qml的UI文件来从UI逻辑中分离UI的视觉部分,UI逻辑您在.qml文件中实现。您应仅使用Qt Design Studio的2D视图编辑UI文件。如果您使用其他工具添加任何Qt Design Studio不支持代码,它将显示错误消息。修复错误以再次启用UI文件的视觉编辑。通常,您应将不受支持的代码移动到.qml文件中。

使用Qt Quick布局

Qt提供Qt Quick Layouts来在布局中视觉化地排列Qt Quick项。与替代方案item positioners相比,Qt Quick Layouts还可以在窗口大小调整时调整其子项的尺寸。尽管Qt Quick Layouts通常是大多数用例的首选选择,但在使用时应考虑以下知其不可不知者为乐

知其不可

  • 使用锚点宽度高度属性来指定布局相对于其非布局父项的大小。
  • 使用布局附加属性来设置布局直接子项的大小和定位属性。

不要做的事情

  • 不要为提供了隐式宽度和高度的项目定义首选大小,除非它们的隐式大小不合适。
  • 不要在布局的直接子项上使用锚点。相反,请使用Layout.preferredWidthLayout.preferredHeight
    RowLayout {
        id: layout
        anchors.fill: parent
        spacing: 6
        Rectangle {
            color: 'orange'
            Layout.fillWidth: true
            Layout.minimumWidth: 50
            Layout.preferredWidth: 100
            Layout.maximumWidth: 300
            Layout.minimumHeight: 150
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
        Rectangle {
            color: 'plum'
            Layout.fillWidth: true
            Layout.minimumWidth: 100
            Layout.preferredWidth: 200
            Layout.preferredHeight: 100
            Text {
                anchors.centerIn: parent
                text: parent.width + 'x' + parent.height
            }
        }
    }

注意:布局和锚点都是占用更多内存和实例化时间的对象类型。如果对x、y、width和height属性的简单绑定就足够了,请避免使用它们(特别是在列表和表格代理,以及控件风格中)。

类型安全

在 QML 中声明属性时,使用“var”类型既简单又方便。

property var name
property var size
property var optionsMenu

但是,这种方法有几个缺点。

  • 如果分配了错误类型的值,错误报告将指向属性声明的位置,而不是将属性分配给的位置。这使得错误跟踪变得更加困难,从而减慢了开发过程。
  • 静态分析无法捕获上述错误。
  • 实际属性的底层类型对读者来说并不总是立即清晰。

因此,尽可能使用实际类型。

property string name
property int size
property MyMenu optionsMenu

性能

有关 QML 和 Qt Quick 的性能信息,请参阅QML 性能考虑和建议

优先使用声明性绑定,而不是命令性赋值

在 QML 中,可以使用命令性 JavaScript 代码来执行诸如响应用件、通过网络发送数据等任务。命令性代码在 QML 中占有重要位置,但也需要注意何时不使用它。

例如,考虑以下命令性赋值

Rectangle {
    Component.onCompleted: color = "red"
}

这有以下缺点

  • 它很慢。颜色属性首先会用默认构造函数评估,然后会在之后用“red”再次评估。
  • 它将编译时可能发现的错误延迟到运行时,从而减慢了开发过程。
  • 它覆盖了之前的声明性绑定。在大多数情况下这是预期的,但有时可能是意外的。有关详细信息,请参阅调试绑定的覆盖
  • 它干扰了工具;例如,Qt Quick Designer 不支持 JavaScript。

可以将代码重写为声明性绑定

Rectangle {
    color: "red"
}

工具和实用程序

有关使 QML 和 Qt Quick 的工作更容易的 useful 工具和 utilies 的信息,请参阅Qt Quick 工具和实用程序

场景图

有关 Qt Quick 的场景图信息,请参阅Qt Quick 场景图

可缩放用户界面

随着显示分辨率的提高,可缩放的应用程序 UI 越来越重要。实现这一目标的一种方法是为不同的屏幕分辨率维护多个 UI 副本,并根据可用的分辨率加载适当的副本。尽管这效果很好,但它增加了维护开销。

Qt 提供了更好的解决方案,并建议应用程序开发者遵循以下建议

  • 使用锚点或 Qt Quick 布局模块来布置视觉项。
  • 不要为视觉元素指定显式的宽度和高度。
  • 为每个支持的显示分辨率提供UI资源,例如图像和图标。Qt Quick控件示例很好地演示了这一点,它提供了qt-logo.png文件,用于@2x@3x@4x分辨率,使得应用能够适应高分辨率显示器。如果显式启用了高DPI缩放功能,Qt将自动选择适合给定显示器的适当图像。
  • 对小图标使用SVG图像。虽然较大的SVG图像可能渲染较慢,但小SVG图像可以很好地工作。矢量图像避免了需要提供多个图像版本的需要,这在位图图像中是必要的。
  • 使用基于字体的图标,例如Font Awesome。这些图标可以适应任何显示分辨率,并允许着色。Qt Quick控件文本编辑示例很好地展示了这一点。

这样一来,您应用程序的UI应根据提供的显示分辨率进行缩放。

© 2024 The Qt Company Ltd. 本文档中的贡献内容归其各自所有者所有。提供的文档受免费软件基金会发布的GNU自由文档许可证版本1.3条款的许可。Qt及其相关标志是The Qt Company Ltd.在芬兰和/或其他国家的商标。所有其他商标均为其各自所有者的财产。