英文原版:https://www.qt.io/product/qt6/qml-book
英文原版Github: https://github.com/qmlbook/qt6book
前言
欢迎!
欢迎阅读《Qt6 QML Book,A book about Qt6》,一本关于 QML 的书籍。本书将引导您学习 QML,Qt 用于创建动态用户界面的语言。
我相信,能够构建声明式、响应式、硬件加速的用户界面,并在所有主流平台(以及一些非主流平台)上以原生性能运行,这绝对是一项颠覆性的变革。刚开始接触 Qt 时,它就像是我快速构建软件的秘密武器。而 QML 则将这种优势提升到了一个新的高度。
您可能会问,这本书与 Qt 官方文档有何不同?本书旨在作为其补充。您可以按顺序阅读本书,每一章都建立在您之前学习的内容之上。同时,本书也可以作为经验丰富的读者了解新主题的入门指南。每一章都专注于一个特定的主题,并介绍 Qt 和 QML 的相关概念。当然,Qt 官方文档始终提供完整的信息,是查找所有元素、属性、枚举等详细信息的绝佳参考资料。祝您阅读愉快!
Johan Thelin
内容组织结构
本书大致分为三个部分。这种划分并非绝对,并非严格意义上的章节划分,而更像是我们在写作过程中遵循的一个指导原则。
前几章,大约到第 5 章到第 7 章,可以看作是入门介绍。如果您想学习 QML,务必阅读这些章节。
接下来的章节,第 6 章到第 14 章,可以看作是相对独立的章节,分别介绍不同的主题,尽管第 7 章中的模型在后续章节中被多次使用。您可以根据自己的喜好选择阅读顺序,学习您感兴趣的主题。
本书的其余部分则侧重于更高级的主题,例如 JavaScript 的细节、C++ 和 QML 的混合使用,以及 Qt for Python 绑定和 QML。这些都是非常重要的主题,我强烈建议您阅读。要使用 QML 构建完整的应用程序,您需要了解这些主题,但它们的主要重点并非 QML。
永不止步
《Qt6 QML Book,A book about Qt6》是一个持续更新项目。我们欢迎贡献者,并计划开放我们的基础设施,以便您能够通过报告问题、提交修复程序和新内容来做出贡献。最终目标是在内容达到我们满意的成熟度后,向您提供纸质书籍。但我们现在就想与您分享这些内容,并从您的反馈中了解哪些方面需要改进,以及需要添加哪些新内容。
致谢
本书的开发离不开 Qt 公司 的慷慨赞助。能够参与这样的项目是我的荣幸,他们的帮助弥足珍贵。在此,我要特别感谢以下人员(按字母顺序排列):
-
empenzes
-
Fabian K
-
Luca Di sera
-
magoldst-qt
-
Maurice Kalinowski
-
Mitch Curtis
-
nezticle
-
Tino Pyssysalo
-
Ulf Hermann
-
Vladimir Minenko
贡献者
本书的开发离不开众多杰出社区贡献者的鼎力支持。我要感谢以下所有人(按字母顺序排列):
-
alexshen
-
arky
-
DavidAdamsPerimeter
-
delvianv
-
guoci
-
nittwitt
-
oleksis
-
LorenDB
-
paulmasri
-
QtSCH
-
ruudschouten
-
task-jp
-
topecongiro
-
VideoCarp
-
wangchunlin5013
本书历史
本书基于The QML Book,该书最初是为Qt 5编写的。我要感谢该书的所有贡献者(按字母顺序排列):
-
aamirglb
-
alexeRadu
-
andreabedini
-
amura11
-
bakku
-
cibersheep
-
dbelyaev
-
danielbaak
-
DocWicking
-
empyrical
-
Ge0
-
gillesfernandez
-
gitter-badger
-
gsantner
-
hckr
-
iitaka1142
-
jiakuan
-
justinfx
-
maggu2810
-
marco-piccolino
-
mariopal
-
mark-summerfield
-
mhubig
-
micdoug
-
Mihaylov93
-
moritzsternemann
-
RossRogers
-
Swordfish90
-
sycy600
-
trolley
-
29jm
我还要特别感谢 Pelagicore、Qt 公司和 Felgo,感谢他们赞助我们的工作,并在反馈和支持方面给予了我们极大的帮助,使《Qt6 QML Book,A book about Qt6》得以顺利编写。
作者
《Qt6 QML Book,A book about Qt6》由以下作者团队撰写:
Johan Thelin

Johan 是一位系统架构师,致力于构建汽车解决方案。他拥有超过二十年基于 Linux、Qt 等技术的设备开发经验。他曾为多家公司撰写论文和博客文章,并在众多会议上发表演讲,同时为软件开发和软件组织提供咨询服务。作为自由开源解决方案的坚定拥护者,他创立并组织了 foss-north 大会。
您可以通过 LinkedIn、他的博客 和 他的个人主页 了解更多关于 Johan 的信息。
Jürgen Bocklage-Ryannel

Jürgen 是 ApiGear 的首席执行官,ApiGear 是一款协作式机器界面设计工具,使团队能够协作设计软件界面,并提供自动化监控和仿真解决方案。
他曾是 Pelagicore AG 的联合创始人,并担任戴姆勒 MBUX 早期版本的首席用户界面架构师。
他目前专注于 API 驱动的工作流程,旨在为不同平台设计和创建用户体验与底层服务之间的接口。
您可以在 LinkedIn 上了解更多关于 Jürgen 的信息。
Cyril Lorquet

Cyril 是比利时公司 Eunoia Studio 的联合创始人兼首席执行官,致力于帮助企业将自身专业知识转化为软件产品。自 2009 年以来,他一直从事各种领域(建筑、医疗保健、水文、市场营销等)的软件产品开发工作,其中一些项目使用了 Qt 框架。作为一名软件工程师,他对设计流程、软件开发和变更管理充满热情。
您可以在 LinkedIn 上了解更多关于 Cyril 的信息。
第1章初识 Qt
Qt和 Qt Quick
本书将带您逐步了解使用全新 Qt 6 进行应用程序开发的各个方面。本书重点介绍 Qt Quick 技术,同时也提供了编写 Qt Quick 的 C++ 后端和扩展所需的必要信息。
本章是对 Qt 6 的概述。它将展示可供开发人员使用的不同应用程序模型,并提供一个示例应用程序,让您先睹为快。此外,本章还旨在全面介绍 Qt 的内容以及如何联系 Qt 的开发商 Qt 公司。
Qt 6 聚焦的内容
Qt 5 发布于多年前,引入了一种全新的声明式方法来编写精美的用户界面。自那时以来,我们周围的世界发生了翻天覆地的变化。
Qt 6 将延续 Qt 5 的成果,并且不会对大多数用户造成干扰。Qt 对用户的价值体现在哪里?
-
跨平台特性
-
可扩展性
-
世界一流的 API 和文档
-
可维护性、稳定性和兼容性
-
庞大的开发者生态系统
Qt 6 将 Qt 产品推向新的市场,同时又紧跟用户价值。
桌面市场是 Qt 产品线的根基。大多数用户都是通过桌面市场首次接触 Qt,它也构成了 Qt 工具及其成功的基础。
预计 Qt 6 将在嵌入式和联网设备市场实现最大增长,涵盖从高端接近桌面性能的设备到微控制器等低端设备。触摸屏在这些设备中的应用将呈指数级增长。许多此类设备的功能相对简单,但需要流畅美观的用户界面。
另一方面,市场对更复杂、集成 2D/3D 的用户界面也有需求。基于 2D 元素的 3D 内容界面将十分常见,增强现实和虚拟现实技术也将得到广泛应用。
互联设备的增长以及对流畅用户界面日益增长的需求,要求我们简化应用程序和设备的开发工作流程。将用户体验设计师融入开发工作流程是 Qt 6 系列的目标之一。
Qt 6 为我们带来:
-
新一代 QML
-
新一代图形
-
统一且一致的工具集
-
增强的 Qts C++ API
-
组件市场
Qt 构建模块
Qt 6 由大量模块组成。一般来说,模块是供开发者使用的库。某些模块对于支持 Qt 的平台是必需的,它们构成了所谓的“Qt Essentials Modules”(Qt 基本模块)。其他模块是可选的,它们构成了“Qt Add-On Modules”(Qt 附加模块)。大多数开发者可能不需要使用后者,但了解它们很有帮助,因为它们为常见的挑战提供了宝贵的解决方案。
Qt 模块
Qt Essentials 模块对于任何支持 Qt 的平台都是必需的。它们为使用 Qt Quick 2 开发现代 Qt 6 应用程序奠定了基础。完整的模块列表可在 Qt 文档模块列表 中找到。
Core-Essentials 模块
开始 QML 编程所需的最小 Qt 6 模块集。
-
Qt Core – 其他模块使用的核心非图形类。
-
Qt D-BUS – 用于在 Linux 系统上通过 D-Bus 协议进行进程间通信的类。
-
Qt GUI – 图形用户界面 (GUI) 组件的基类。包含 OpenGL。
-
Qt Network – 使网络编程更轻松、更具可移植性的类。
-
Qt QML – 用于 QML 和 JavaScript 语言的类。
-
Qt Quick – 用于构建具有自定义用户界面的高度动态应用程序的声明式框架。
-
Qt Quick Controls – 提供轻量级的 QML 类型,用于为桌面、嵌入式和移动设备创建高性能用户界面。这些类型采用简单的样式架构,效率极高。
-
Qt Quick Layouts – 布局是用于在用户界面中排列基于 Qt Quick 2 的项目的组件。
-
Qt Quick Test – 一个用于 QML 应用程序的单元测试框架,其中测试用例以 JavaScript 函数的形式编写。
-
Qt Test – 用于对 Qt 应用程序和库进行单元测试的类。
-
Qt Widgets – 用于使用 C++ 控件扩展 Qt GUI 的类。
graph BT
QtCore-->QtNetwork
QtCore-->QtGui
QtGui-->QtWidgets
QtCore-->QtQml
QtCore-->QtTest
QtQml-->QtQuick
QtQuick --> QtQuickTest
QtQuick --> QtQuickLayout
QtQuick --> QtQuickControls

Qt 附加模块
除了基本模块之外,Qt 还提供针对特定用途的附加模块。许多附加模块要么功能齐全且仅用于向后兼容,要么仅适用于某些平台。这里列出了一些可用的附加模块,但请务必熟悉所有模块,您可以参考Qt 文档附加模块列表以及下面的列表。
-
网络:Qt 蓝牙 / Qt 网络授权
-
UI 组件:Qt Quick 3D / Qt Quick 时间线 / Qt 图表 / Qt 数据可视化 / Qt Lottie 动画 / Qt 虚拟键盘
-
图形:Qt 3D / Qt 图像格式 / Qt OpenGL / Qt 着色器工具 / Qt SVG / Qt Wayland 合成器
-
辅助工具:Qt 5 核心兼容 API / Qt 并发 / Qt 帮助 / Qt 打印支持 / Qt Quick 小部件 / Qt SCXML / Qt SQL / Qt 状态机 / Qt UI 工具 / Qt XML
::: 提示
由于这些模块不包含在本次发布版本中,因此每个模块的状态可能因活跃贡献者的数量和测试的完善程度而有所不同。
:::
支持的平台
Qt 支持多种平台,包括所有主流桌面和嵌入式平台。借助 Qt 平台抽象,现在比以往任何时候都更容易将 Qt 移植到您自己的平台上(如果需要的话)。
在某个平台上测试 Qt 6 非常耗时。Qt 项目选择了一个平台子集来构建参考平台集。这些平台经过系统测试的全面测试,以确保最佳质量。但是,请记住,任何代码都不可能完全没有错误。
Qt 项目
来自 Qt Wiki:
“Qt Wiki 是一个基于共识、精英管理的 Qt 社区。任何对此感兴趣的人都可以加入社区,参与决策过程,并为 Qt 的开发做出贡献。”
Qt Wiki 是 Qt 用户和贡献者分享见解的地方。它为其他用户贡献内容奠定了基础。最大的贡献者是 Qt 公司,该公司也拥有 Qt 的商业权利。
Qt 既有开源的一面,也有面向企业的商业一面。商业版面向那些无法或不愿遵守开源许可协议的公司。如果没有商业版,这些公司将无法使用 Qt,Qt 公司也无法为 Qt 项目贡献如此多的代码。
全球有许多公司依靠在各种平台上使用 Qt 进行咨询和产品开发来维持运营。还有许多开源项目和开源开发者将 Qt 作为其主要开发库。能够成为这个充满活力的社区的一份子,并使用这些优秀的工具和库,感觉真好。这会让你变得更好吗?也许吧:-)
贡献链接:http://wiki.qt.io/
Qt 6 简介
Qt Quick
Qt Quick 是 Qt 6 中使用的用户界面技术的统称。它最初在 Qt 4 中引入,现在已扩展到 Qt 6。Qt Quick 本身是多种技术的集合:
-
QML – 用户界面标记语言
-
JavaScript – 动态脚本语言
-
Qt C++ – 高度可移植的增强型 C++ 库

与 HTML 类似,QML 是一种标记语言。它由标签(在 Qt Quick 中称为类型)组成,这些标签用花括号 Item {} 括起来。QML 从一开始就被设计用于创建用户界面,并提高开发人员的开发速度和可读性。可以使用 JavaScript 代码进一步增强用户界面。Qt Quick 可以使用 Qt C++ 轻松扩展您自己的原生功能。简而言之,声明式 UI 称为前端,而原生部分称为后端。这样可以将应用程序的计算密集型原生操作与用户界面部分分离。
在一个典型的项目中,前端使用 QML/JavaScript 开发。后端代码(负责与系统交互并执行繁重的计算任务)则使用 Qt C++ 开发。这使得设计型开发人员和功能型开发人员之间能够自然地进行分工。通常,后端会使用 Qt Test(Qt 的单元测试框架)进行测试,并将测试结果导出供前端开发人员使用。
用户界面示例
让我们使用 Qt Quick 创建一个简单的用户界面,以展示 QML 语言的一些特性。最终,我们将得到一个带有旋转叶片的纸风车。

我们首先创建一个名为 main.qml 的空文档。所有 QML 文件都将以 .qml 为后缀。作为一种标记语言(类似于 HTML),QML 文档必须且只能有一个根类型。在本例中,我们使用 Image 类型,其宽度和高度基于背景图像的几何形状:
import QtQuick
Image {
id: root
source: "20260602_background.png"
}
由于 QML 对根类型的选择没有限制,我们使用 Image 类型,并将 source 属性设置为我们的背景图像作为根。

::: 提示
每种类型都有属性。例如,图像类型具有 width 和 height 属性,分别表示像素数。它还有其他属性,例如 source。由于图像类型的大小会自动从图像大小派生而来,因此我们不需要自己设置 width 和 height 属性。
:::
最常用的类型位于 QtQuick 模块中,可以通过 .qml 文件开头的 import 语句导入该模块。
id 是一个特殊的可选属性,它包含一个标识符,可用于在文档的其他位置引用其关联的类型。重要提示:id 属性一旦设置就无法更改,也不能在运行时设置。本书约定使用 root 作为根类型的 id,以便在较大的 QML 文档中更准确地引用最顶层的类型。
用户界面中的前景元素(代表杆子和风车)以单独的图像形式包含。


我们希望将杆子水平放置在背景中心,但垂直向下偏移。同时,我们希望将风车放置在背景中心。
虽然这个入门示例仅使用图像类型,但随着学习的深入,您将创建由多种不同类型组成的更复杂的用户界面。
Image {
id: root
...
Image {
id: pole
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
source: "images/pole.png"
}
Image {
id: wheel
anchors.centerIn: parent
source: "images/pinwheel.png"
}
...
}
要将风车放置在中心,我们使用一个名为 anchors 的复杂属性。锚定允许您指定父对象和兄弟对象之间的几何关系。例如,将我放置在另一个类型的中心(anchors.centerIn: parent)。两端都有 left、right、top、bottom、centerIn、fill、verticalCenter 和 horizontalCenter 关系。当然,当两个或多个锚点一起使用时,它们应该相互补充:例如,将一个类型的左侧锚定到另一个类型的顶部是没有意义的。
对于风车图案,锚定只需要一个简单的锚点。
::: 提示
有时您可能需要进行一些微调,例如,将某个文字稍微偏离中心。这可以通过 anchors.horizontalCenterOffset 或 anchors.verticalCenterOffset 来实现。所有其他锚点也都有类似的调整属性。有关锚点属性的完整列表,请参阅文档。
:::
::: 提示
将图像作为根类型(Image)的子类型放置,可以演示图像的放置。