# 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类型作为根类型,并将源属性设置为我们的背景图像。

提示

每种类型都有属性。 例如,图像具有widthheight属性,每个属性都控制一个像素数量。 它还具有其他属性,例如source属性。 由于图片类型的尺寸自动来源于图片尺寸,我们不需要自己设置widthheight属性。

最标准的类型位于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.horizontalCenterOffsetanchors.verticalCenterOffset 来完成。 所有其他锚点也可以使用类似的调整属性。有关锚点属性的完整列表,请参阅文档。

提示

将图像作为我们的根类型(Image)的子类型说明了声明性语言的一个重要概念。 按层和分组的顺序描述用户界面的视觉外观,其中最顶层(背景图像)首先绘制,它的子层在它(表示包裹子层类型的类型)的局部坐标系中绘制并放在它的顶部。

为了使展示更有趣,让我们使场景具有交互性。 当用户在场景中某处按下鼠标时旋转纸风车。

我们使用 MouseArea 类型并使其覆盖我们根类型的整个区域。

Image {
    id: root
    ...
    MouseArea {
        anchors.fill: parent
        onClicked: wheel.rotation += 90
    }
    ...
}

当用户在其覆盖的区域内单击时,鼠标区域会发出信号。 您可以通过覆盖 onClicked 函数来连接到这个信号。 当一个信号被连接时,这意味着它所对应的函数(或多个函数)在发出信号时被调用。 在这种情况下,当鼠标点击鼠标区域时,idwheel的类型(即纸风车图像)应该旋转+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编程工作的基础知识有了非常简要的了解。

最后更新: 11/20/2021, 6:47:04 PM