开篇
在《QML | 创建可重用的组件》一文中,描述了创建自定义组件的第一种方法。本文将来描述第二种方法:
使用Component创建自定义组件
该种方法在实际使用中,可有两种方式:
-
(1)在qml文件内创建自定义的组件
-
(2)以qml文件的方式创建组件。
在qml文件内创建自定义的组件
组件通常由组件文件定义,也就是.qml文件。Component类型允许在一个QML文档内定义QML组件
,而不用作为一个单独的QML文件,例如如下代码:
该组件的封装代码是放置于main.qml这个应用根描述文件中的,我们运行一下:
将得到一个空白的窗体。
如果我们要使用这个组件,我们可以使用Loader
类型,该QML类型用于:动态加载QML组件。
这时候会动态加载这个组件,运行则可以看见一个蓝色的矩形:
也可以使用Loader创建多个矩形:
运行效果如下:
综上可见,虽然矩形本身会自动渲染和显示,但在Component中定义的则不会这样。因为Component将QML类型封装在内部,就好像它们是在一个单独的QML文件中定义的,直到请求时(在本例中,使用Loader
类型)才加载。理解了这一点,如果代码这些写:
结果则是:无法运行程序
。因为这种写法在本质上是没有QML根元素的。因此需注意:
在Component类型封装的QML组件中不能存在多个同级的QML类型,只能存在一个根元素。
使用Component在qml文件内创建组件不能直接实例化,可以结合:Loader、Repeater、View视图、脚本来使用。下文将描述使用Component创建多个qml组件。
使用Component创建多个qml组件
使用Component创建多个qml组件在实际的QML应用开发中是一种较为常用的方法,因为一个应用软件,会包含多个软件UI,例如下图所示效果:
在上图所示的窗体中会有四个按钮,分别为:page_1、page_2、page_3、page_4。当我们在点击其中的按钮后,会跳转到对应的页面,然而在页面中又有其他的QML类型和逻辑。这时候则需要使用Component来封装不同页面的组件。以上图效果为例,则需要创建四个不同的页面描述qml文件,这里文件名称如下:
然后使用Component创建四个页面qml组件,例如下例代码:
在实际开发中,对于不同的页面参数有所不同的,还可以将属性导出,在对应的组件实例下设置参数,从而设置不同的页面参数。
运行看一下效果:
附上main.qml文件代码:
import QtQuick 2.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.0
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.0
import QtQuick.Window 2.1
Window {
id: window
visible: true
width: 350
height: 500
title: qsTr("iriczhao | 使用Component创建组件")
//页面一
property Component page1: Page1View{}
//页面二
property Component page2: Page2View{}
//页面三
property Component page3: Page3View{}
//页面四
property Component page4: Page4View{}
//创建组件映射
property var componentMap: {
"page_1": page1,
"page_2": page2,
"page_3": page3,
"page_4": page4
}
//创建StackView
StackView {
id: stackView
anchors.fill: parent
initialItem: ListView {
model: ListModel {
ListElement {
title: "page_1"
}
ListElement {
title: "page_2"
}
ListElement {
title: "page_3"
}
ListElement {
title: "page_4"
}
}
delegate: Button {
width: stackView.width
height: 50
text: title
style: BlackButtonStyle {
fontColor: "#e7e7e7"
rightAlignedIconSource: "qrc:/images/icon-go.png"
}
onClicked: {
if (stackView.depth == 1) {
stackView.push({item: componentMap[title]});
stackView.currentItem.forceActiveFocus();
}
}
}
}
}
//创建返回按钮
Button{
x: 138
y: 409
text: "return"
anchors.bottom: stackView.top
anchors.bottomMargin: -432
onClicked: {stackView.pop({item: componentMap[title]});}
}
}
总结
本文使用Component
来创建自定义组件,准确来说,应该是创建和加载组件。我们可以在单个qml文件中使用Component
创建组件,然后使用Loader、Repeater来加载组件;也可以将组件划分为具体的qml文件(即以qml文件来表示单个组件
),然后再使用Component来加载。