# Qt 6 介绍
# Qt Quick
Qt Quick是Qt 6中使用的用户界面技术的总称。它是在Qt 5中引入的,现在在Qt 6中进行了扩展。Qt Quick本身是几种技术的集合:
- QML - 用户界面的标记语言
- JavaScript - 动态脚本语言
- Qt C++ - 高度可移植的增强型 C++ 库
与HTML类似,QML是一种标记语言。它由标记(tag)组成,在Qt Quick中称为类型(type),用大括号括起来:Item {}
。它是从头开始设计的,旨在为开发人员创建用户界面,并能快速和轻松地阅读。可以使用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: "images/background.png"
}
由于QML不限制根类型的类型选择,我们使用Image
类型作为根类型,并将源属性设置为我们的背景图像。
提示
每种类型都有属性。 例如,图像具有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"
}
...
}
为了将纸风车放置在中间,我们使用了一个名为anchor
的复杂属性。 锚定允许您指定父对象和兄弟对象之间的几何关系。 例如,将我放在另一种类型的中心(anchors.centerIn: parent
)。 两目标上存在left、right、top、bottom、centerIn、fill、verticalCenter和horizontalCenter关系。 自然地,当两个或多个锚点一起使用时,它们应该相互补充:例如,将一个类型的左侧锚定到另一个类型的顶部是没有意义的。
对于纸风车,锚定只需要一个简单的锚。
提示
有时您会想要进行小的调整,例如,将字体稍微偏离中心。 这可以通过 anchors.horizontalCenterOffset
或 anchors.verticalCenterOffset
来完成。 所有其他锚点也可以使用类似的调整属性。有关锚点属性的完整列表,请参阅文档。
提示
将图像作为我们的根类型(Image
)的子类型说明了声明性语言的一个重要概念。 按层和分组的顺序描述用户界面的视觉外观,其中最顶层(背景图像)首先绘制,它的子层在它(表示包裹子层类型的类型)的局部坐标系中绘制并放在它的顶部。
为了使展示更有趣,让我们使场景具有交互性。 当用户在场景中某处按下鼠标时旋转纸风车。
我们使用 MouseArea
类型并使其覆盖我们根类型的整个区域。
Image {
id: root
...
MouseArea {
anchors.fill: parent
onClicked: wheel.rotation += 90
}
...
}
当用户在其覆盖的区域内单击时,鼠标区域会发出信号。 您可以通过覆盖 onClicked
函数来连接到这个信号。 当一个信号被连接时,这意味着它所对应的函数(或多个函数)在发出信号时被调用。 在这种情况下,当鼠标点击鼠标区域时,id
为wheel
的类型(即纸风车图像)应该旋转+90度。
提示
此技术适用于每个信号,命名约定为on
+ SignalName
。 此外,所有属性在其值更改时都会发出信号。 对于这些信号,命名约定是:
`on${property}Changed`
例如,如果width
属性发生了变化,你可以通过onWidthChanged: print(width)
来观察它。
现在,只要用户点击,轮子就会旋转,但旋转时发生了跳变,而不是随着时间的流逝而运动。 我们可以使用动画来实现平滑的运动。 动画定义了一段时间上发生的属性变化。 为了实现这一点,使用Animation
类型的Behavior
属性。 Behavior
为应用到该属性的每次更改指定一个已定义应用到该属性的动画。 换句话说,只要属性发生变化,动画就会运行。 这只是在QML中制作动画的众多方法之一。
Image {
id: root
Image {
id: wheel
Behavior on rotation {
NumberAnimation {
duration: 250
}
}
}
}
现在,每当纸风车的旋转属性发生变化时,它将使用持续时间为250毫秒的NumberAnimation
动画处理。 因此,每90度转弯将花费250毫秒,从而产生良好的平滑旋转。
提示
实际上不会看到纸风车模糊。 这只是为了体现它的旋转。 (如果想试验一下的话,一个模糊的纸风车在assets文件夹中。)
现在风车外观上看起来挺好,行为也很好,并且提供了对如何使用Qt Quick编程工作的基础知识有了非常简要的了解。