QML引擎和对象树
QML应用软件的开发本质则是:构建一棵QML类型对象树
,这颗对象树绝大部分代码会使用json
和JavaScript
语言来描述。这棵对象树的树根则是一个xxx.qml文件,该文件一般由qml引擎加载和解析,而qml引擎的创建则在一个C++文件的main()
函数中。
qml引擎由QQmlEngine
类代表。该类为实例化QML组件提供了环境。当然在实际开发中,有QQuickeView
、QQuickWidget
、QQuickWindow
等使用。在大多数情况下,还是使用QQmlEngine
类或者其子类QQmlApplicationEngine
,例如下列代码:
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
//载入qml文件
engine.load(url);
return app.exec();
}
所以,用于描述应用软件对象树树根的qml文件(上述代码则是main.qml
),则是一个极其重要的文件了,是qml应用的“灵魂”,小生把她称之为:应用根描述文件
。
在我们的实际QML开发过程中,大部分工作则是规划QML应用界面的组成和结构,以及界面之间的交互和切换流程,最后这些思考会提现在应用根描述文件中。在根描述文件中的代码一般为以下几种:
(1)支撑qml应用的顶层QML类型对象:例如:Window
、ApplicationWindow
、Page
等。
(2)自定义的QML类型对象。
(3)JavaScript代码。
创建可重用的组件
本小节的组件可以理解为自定义的QML类型,回到自定义QML类型对象这个主题,为了在应用根描述文件中创建自定义的QML对象,我们则需要创建该QML类型。因为其是自定义的,一般情况下不会是官方提供的QML类型,而是多个QML类型、JavaScript、信号、属性等的组合。
创建自定义的用户组件有两种方式:
1、自定义Item。
2、使用Component创建自定义组件。
(1)自定义Item
对于自定义Item,我们需要根据实际的自定义特征选择根元素,例如如果自定义是按钮类的类型,则根元素可以选择Button
;如果自定义的是图片相关的类型,则可以使用Image
作为根元素。一般情况下,在QML开发中,所有可视QML类型的根都是Item,所以我们也可以使用Item来作为我们自定义类型的根元素,还常常使用Rectangle
。不同层级的QML类型所拥有的属性和方法不同,在实际使用中根据自定义特征选择即可。
本文将以一个加载指示器
来描述如何自定义QML类型。如下图所示:
首先为自定义的QML类型想一个名称,这里命名为CusBusyIndicator.qml
:然后在该文件中写入自定义的QML描述代码,因这里描述的是一个加载指示器,采用图片旋转的方法来实现,因此其根元素则是Image
,然后使用NumberAnimation
数值动画来改变rotation
参数实现图片旋转,从而做出加载的效果。代码如下:
//CusBusyIndicator.qml
import QtQuick 2.0
Image {
id: container
property bool on: true
source: "images/busy.png"; visible: container.on
NumberAnimation on rotation { running: container.on; from: 0; to: 360; loops: Animation.Infinite; duration: 1200 }
}
至此,我们已经创建好了一个自定义的类型:加载指示器,接下来,则需要在应用程序中使用了(其使用方法与Qt提供的QML类型一样),在主元素创建即可。如下代码:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.0
Window {
id: window
width: 500
height: 500
visible: true
color: "#99c4e9"
title: qsTr("iriczhao | 自定义QML类型")
Rectangle{
anchors.fill: parent
anchors.rightMargin: 200
anchors.leftMargin: 200
anchors.bottomMargin: 200
anchors.topMargin: 200
CusBusyIndicator{
anchors.fill: parent
}
}
}
运行效果如下
综上,创建自定义的QML类型,需要注意以下几点:
定义在单独的文件中,且文件名首字母大写!
每个文件有一个主元素。
与标准QML类型使用方法一样(可直接以文件名称引入)
总结
在QML创建自定义的组件,则需要创建一个以qml后缀结束的文件,且文件名称的首字母必须大写(这一点非常重要,默认情况下QtCerator和QtDesigner Studio都是创建大写字母开始的文件,但也不排除手动创建的文件首字母是以小写字母创建的)。
创建自定义的组件有两种方法:
1、自定义Item。
2、使用Component创建自定义组件。