转自:https://blog.csdn.net/douzhq/article/details/81046681
本篇文章介绍一下QML中的组件,Component
1. 使用Component在QML中嵌入组件
Component是Qt框架或者开发者封装好的、只暴露必要接口的QML类型,可以重复使用。要再QML中嵌入Component的定义,需要使用Component对象。
- Component只能包含一个顶层的Item,而且在这个Item之外不能定义任何的数据,除了Id。
- Component通常用来给一个View提供图形化组件。
- Component不是Item的派生类,而是从QQmlComponent继承而来的,虽然它通过自己的顶层Item为其他的View提供可视化组件,但它本身不是可见元素。
下面是一个简单的在QML文档中定义Component的示例:
Component {
id: itemCompont
Rectangle {
id: compontRect
color: 'blue'
implicitWidth: 200
implicitHeight: 50
signal deleteThis()
Text {
id: interText
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
text: qsTr("text")
}
Button {
anchors.margins: 5
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
text: '删除'
onClicked: {
compontRect.deleteThis()
}
}
}
}
2. 在文件中定义组件
很多时候我们把QML文件定义在一个文件中,方便被其他的QML文件调用。可以直接使用文件名作为组件的名称,在其他的QML文件中使用。上面组件中的代码可以单独定义在一个文件中,本示例的文件名为TestCompont.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
Rectangle {
id: compontRect
color: Qt.rgba(0.8, 0.4, 0.4, 1.0)
implicitWidth: 200
implicitHeight: 50
property var currentObject: ''
signal deleteThis(var obj)
// 设置文字的内容
function setCurrentText(textName) {
interText.text = textName
}
Text {
id: interText
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
text: qsTr("text")
}
Button {
anchors.margins: 5
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
text: '删除'
onClicked: {
compontRect.deleteThis(compontRect)
}
}
Component.onCompleted: {
compontRect.currentObject = parent
}
}
3. 使用Loader加载/删除组件
Loader用来动态加载QML组件。
- source属性,加载一个QML文档。
- sourceComponent属性,加载一个Component对象。
- 当source或sourceComponent属性发生变化时,它之前的对象会被销毁,新对象会被加载。
- 当source设置为空串,或者sourceComponent设置为undefined,将会销毁当前对象,相关资源也会被释放,Loader对象会变成一个空对象。
- item属性指向他加载的组件的顶层Item,比如上面的示例item就为Rectangle。
下面是一个使用Loader加载/删除组件的一个示例,效果如下:
上面的红色Item为直接使用Component的Loader,下面为从文件中加载的组件。
代码如下:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
Window {
width: 800
height: 600
visible: true
Rectangle {
id: mainRect
anchors.fill: parent
Loader {
id: loader1
sourceComponent: itemCompont
anchors.top: parent.top
anchors.topMargin: 10
width: mainRect.width
height: 50
function onDisDeleteThis() {
loader1.sourceComponent = undefined
}
onLoaded: {
item.color = 'red'
loader1.item.deleteThis.connect(loader1.onDisDeleteThis)
}
}
Loader {
id: loader2
source: 'qrc:/QML/TestCompont.qml'
anchors.top: loader1.bottom
anchors.topMargin: 10
width: mainRect.width
height: 50
function onDisDeleteThis() {
loader2.source = ''
}
onLoaded: {
loader2.item.deleteThis.connect(loader2.onDisDeleteThis)
}
}
Component {
id: itemCompont
Rectangle {
id: compontRect
color: 'blue'
implicitWidth: 200
implicitHeight: 50
signal deleteThis()
Text {
id: interText
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
text: qsTr("text")
}
Button {
anchors.margins: 5
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
text: '删除'
onClicked: {
compontRect.deleteThis()
}
}
}
}
}
}
4. 使用JavaScript中的语句加载/删除组件
QML支持使用JavaScript动态创建/销毁对象,有两种方式动态创建对象:
- 使用Qt.createComponent()动态创建一个组件对象,然后使用Component的createObject()方法创建对象。
- 使用Qt.createQmlObject()从一个QML字符串直接创建一个对象。
如果QML文件中嵌入Component,可以直接使用这个组件的createObject()方法创建组件;使用Component的destroy()方法删除已经创建的组件。destroy()方法可以指定一个延时,不过不指定,他会在适当的时候删除。
下面是一个简单的示例:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.4
Window {
width: 800
height: 600
visible: true
Rectangle {
id: mainRect
anchors.fill: parent
property var mainRectComponent: null
Column {
id: mainColumn
spacing: 5
width: parent.width
property var count: 0
function deleteItems(object) {
object.destroy()
}
function createItem() {
var color = 'red'
if (mainColumn.count % 3 === 1)
color = 'yellow'
else if (mainColumn.count % 3 === 2)
color = 'blue'
mainColumn.count++
// 创建一个组件
var obj = itemCompont.createObject(mainColumn, {"color": color, "width": mainRect.width})
//obj.setCurentObject(obj)
obj.setCurrentText('Component' + mainColumn.count.toString())
obj.deleteThis.connect(mainColumn.deleteItems)
// 创建文件中的组件
var obj2 = mainRect.mainRectComponent.createObject(mainColumn,
{'color': Qt.rgba(0.4, 0.8, 0.6, 1.0)
,'width': mainRect.width})
obj2.setCurrentText('Component' + mainColumn.count.toString() + ', From File TestComponent')
obj2.deleteThis.connect(mainColumn.deleteItems)
}
}
Button {
anchors.top: mainColumn.bottom
anchors.topMargin: 10
anchors.right: mainRect.right
anchors.rightMargin: 10
text: '添加'
onClicked: {
mainColumn.createItem()
}
}
Component.onCompleted: {
if (mainRectComponent == null)
mainRectComponent = mainRectComponent = Qt.createComponent('qrc:/QML/TestCompont.qml')
}
Component {
id: itemCompont
Rectangle {
id: compontRect
color: 'blue'
implicitWidth: 200
implicitHeight: 50
property var currentObject: ''
signal deleteThis(var obj)
// 设置文字的内容
function setCurrentText(textName) {
interText.text = textName
}
Text {
id: interText
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
text: qsTr("text")
}
Button {
anchors.margins: 5
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
text: '删除'
onClicked: {
compontRect.deleteThis(compontRect)
}
}
Component.onCompleted: {
compontRect.currentObject = parent
}
}
}
}
}
Component.createObject()的方法,第一个参数指定它的父对象,第二个参数可以指定这个组件的一些参数。
代码的显示效果如下: