QML和Qt Quick的最佳实践#

列出了与QML和Qt Quick一起工作的最佳实践。

尽管QML和Qt Quick提供了诸多好处,但在某些情况下它们可能会有挑战性。以下部分详细说明了某些最佳实践,这将有助于您在开发应用程序时获得更好的结果。

自定义UI控件#

流畅且现代的UI对于任何应用程序在当今世界的成功至关重要,这正是QML对设计师或开发者来说如此有吸引力的地方。Qt提供了创建流畅且看起来现代化的UI所必需的基本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_FILES下列出的所有QML文件都将提前自动编译。

您应该使用qt_add_qml_module将QML文件与CMakeLists.txt文件放在同一目录下。否则,它们的隐式导入将与它们所属的QML模块不一致。这是错误的常见来源。

相关信息#

  • Qt资源系统

分离UI与业务逻辑#

大多数应用程序开发者想要实现的关键目标之一是创建一个可维护的应用程序。实现这一目标的方法之一是将用户界面与业务逻辑分离。以下是一些为什么应用程序的 UI 应该使用 QML 编写的原因:

  • 声明性语言非常适合定义 UI。

  • 由于 QML 代码比 C++ 代码更简洁,且不是强类型,因此编写起来更简单。这也使其成为原型设计的优秀语言,这一点在与设计师协作时至关重要。

  • 在 QML 中可以轻松使用 JavaScript 响应事件。

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

Qt 提供了各种方法将 QML 和 C++ 代码集成到应用程序中。一个典型的用例是在用户界面中显示数据列表。如果数据集是静态的、简单的或小型,则可以使用 QML 编写的模型就足够了。

以下是一个用 QML 编写的模型的示例片段

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

从 C++ 中暴露数据到 QML#

重构 QML 比重构 C++ 更容易,因此为了使维护轻松,我们应该尽可能让 C++ 类型不了解 QML。这可以通过“推送”C++ 类型到 QML 中来实现。

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

在此方法中,如果 QML 今后需要重构,则 C++ 保持不变。

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

相关信息#

  • 使用 C++ 编写 QML 扩展教程

  • 聊天应用程序教程

使用 Qt Design Studio#

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

相关信息#

  • Qt Design Studio:UI 文件

使用 Qt Quick 布局#

Qt 提供了 Qt Quick 布局来在布局中可视地排列 Qt Quick 项目。与选择性布置程序不同,Qt Quick 布局还可以在窗口调整大小时调整其子项的大小。虽然 Qt Quick 布局通常是大多数情况下的首选选择,但使用时必须考虑以下 dodon’t

do 的规则#

  • 使用锚点宽度高度属性来指定布局相对于其非布局父项的大小。

  • 使用布局附加属性来设置布局的立即子项的大小和定位属性。

不应做的

  • 不要为具有隐式宽度和高度的项定义首选大小,除非它们的隐式大小不令人满意。

  • 不要在布局的直接子项上使用锚点。相反,请使用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"
}

这有几个缺点

  • 它的速度很慢。颜色属性首先将使用默认构造值评估,然后稍后再次使用“红色”。

  • 它延迟了可以在构建时发现的错误,直到运行时,从而减慢了开发过程。

  • 它覆盖了任何现有的声明式绑定。在大多数情况下这是故意的,但有时可能是无意为之。有关更多信息,请参阅调试绑定覆盖。

  • 它与工具冲突;例如,Qt Quick Designer不支持JavaScript。

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

Rectangle {
    color: "red"
}

工具和实用程序

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

场景图

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

可伸缩的用户界面#

随着显示分辨率的提升,可伸缩的应用程序用户界面变得越来越重要。实现这一目标的方法之一是维护不同屏幕分辨率的多个UI副本,并根据可用的分辨率加载适当的一个。虽然这种方法效果相当好,但增加了维护开销。

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

  • 使用锚点或Qt Quick布局模块来布局视觉元素。

  • 不要为视觉元素指定显式的宽度和高度。

  • 为你的应用程序支持的每个显示分辨率提供UI资源,如图像和图标。Qt Quick控件画廊示例通过提供针对@2x@3x@4x分辨率的qt-logo.png来很好地演示了这一点,从而让应用程序能够满足高分辨率显示屏的需求。如果显式启用了高DPI缩放功能,Qt将自动选择适合给定显示的适当图像。

  • 使用SVG图像作为小图标。虽然较大的SVG可能渲染较慢,但小SVG运行良好。矢量图像避免了需要提供多个图像版本的需求,这对于位图图像来说是必要的。

  • 使用基于字体的图标,例如Font Awesome。这些图标在任何显示分辨率下都可以缩放,并且还允许着色。Qt Quick控件文本编辑器示例很好地展示了这一点。

做到这一点后,你的应用程序的UI应根据所提供的显示分辨率进行缩放。

../_images/qtquickcontrols-gallery-welcome.png

相关信息#

  • 画廊示例

  • 文本编辑器示例

  • Font Awesome

  • 可伸缩性

  • 高DPI