您的位置:首页 > 其它

QML如何创建动态组件

2014-12-12 16:17 405 查看
QML动态组件指的是按需分配,需要时我们就创建一个自定义组件,也就是所谓的对象延迟实例化,而不是在程序一开始就创建它,不需要时我们就把它销毁以节约内存,而不是传统意义上的隐藏或覆盖。我们可以使用Component与Loader,也可以使用JavaScript的形式来完成。
先来介绍一下Component——
progress属性,加载组件的过程,从0.0到1.0变化。
status属性,加载组件的状态,其枚举值分别是Component.Null/Ready/Loading/Error。
url属性,组件路径。
completed()附加信号,对象实例化完成后触发。
destruction()附加信号,对象开始销毁时触发。
object createObject(Item
parent, object properties)函数,创建对象。
string errorString()函数,错误描述。
object incubateObject(Item
parent, object properties,
enumeration
mode)函数,通过mode参数来异步或同步创建对象,mode的值可以是Qt.ASynchronous/Synchronous,默认为异步,返回值的属性有status、object、onStatusChanged、forceCompletion(),其中
forceCompletion()函数强制同步创建对象。
再来看一下Loader——
active属性,默认为true,设置成false时将不能加载组件。
asynchronous属性,默认为false,设置成true时异步加载组件。
item属性,只读属性,保存了成功加载的组件。
progress属性,只读属性,从0.0到1.0变化。
source属性,加载的组件是一个独立的QML文件。
sourceComponent属性,在同一个QML文件中加载组件。
status属性,加载组件的状态,其枚举值分别是Loader.Null/Ready/Loading/Error。
loaded()信号,组件成功加载时触发。
object setSource(url
source, object properties)函数,设置预加载组件路径。
在同一个QML文件中使用ComponentLoader——
Component可封装我们想要的东西,对外只提供一个定义好的接口,也就是其id属性,然后我们就可以重复使用它了。如果某个QML文件重复使用的Component比较小,或者说Component在逻辑上属于某个QML文件,那么该Component就应该在这个QML文件中定义,此时的Loader用到的就是其sourceComponent属性,如下例子:
import QtQuick 2.2

Rectangle {
width: 360; height: 360
color: "lightblue"

MouseArea {
anchors.fill: parent
onClicked: {
loader.sourceComponent = component
loader2.sourceComponent = component
}
}

Component {
id: component
Rectangle {
width: 80; height: 80
color: "red"
}
}

Loader { id: loader }
Loader {
id: loader2;
anchors.centerIn: parent
onLoaded: item.color = "green"
}
}

由于Component不是继承自Item,所以使用anchors锚布局无效,但Loader可以使用。例子中单击鼠标时创建了两个组件,双击鼠标时又把这两个组件销毁了,销毁时需要设置sourceComponent属性值为undefined。
组件分离——
QML文件本身也可以是一个Component,这样就与使用它的QML文件分离开了,这样做的好处是该Component可以被多个QML文件使用,代码结构也清晰明了,此时的Loader用到的就是其source属性,如下例子:
// comp.qml as a separated Component
import QtQuick 2.2

Item {
Row {
spacing: 5
Rectangle {width: 80; height: 80; color: "red" }
Rectangle {width: 80; height: 80; color: "yellow" }
Rectangle {width: 80; height: 80; color: "green" }
}
}

// main.qml
import QtQuick 2.2

Rectangle {
width: 360; height: 360
color: "lightblue"

MouseArea {
anchors.fill: parent
onClicked: {
loader.source = "comp.qml"
loader2.source = "comp.qml"
}
onDoubleClicked: {
loader.source = ""
loader2.source = ""
}
}

Loader { id: loader}
Loader { id: loader2; y: 100}
}

例子中单击鼠标时从外部加载了两个组件,双击鼠标时又把这两个组件销毁了,销毁时需要设置source属性值为“”即一个空值。
QML文件中创建——
先使用Qt.createComponent(url,
mode, parent)从QML文件中创建一个组件,必要时可以根据Component.status属性判断创建状态,然后使用Component.createObject()在某个父对象下实例化对象,最后使用destroy()销毁对象,函数参数可以指定一个时间,单位是毫秒,默认为0,如下例子:
import QtQuick 2.2

Rectangle {
property var object
property var component

width: 360; height: 360
color: "lightblue"

MouseArea {
anchors.fill: parent
onPressed: {
component = Qt.createComponent("comp.qml")
if(Component.Ready === component.status) {
object = component.createObject(parent)
}
}
onReleased: {
object.destroy(2000)
}
}
}

例子中按下鼠标时从QML文件中创建了一个组件component并实例化一个对象object,释放鼠标时在2000毫秒后对象object销毁,但组件component还是存在的。
QML字符串中创建——
使用Qt.createQmlObject(string
qml, object parent, string filepath)从QML字符串中创建,第一个参数是要创建对象的QML字符串,第二个参数指定要创建对象的父对象,第三个参数用于报告错误,例子如下:
import QtQuick 2.2

Rectangle {
property var object

width: 360; height: 360
color: "lightblue"

MouseArea {
anchors.fill: parent
onPressed: object = Qt.createQmlObject('import QtQuick 2.2; Rectangle { color: "red"; width: 100; 	height: 100; anchors.centerIn: parent }', parent, "dynamicSnippet")
onReleased: object.destroy(1000)
}
}

如果修改例子中Qt.creatQmlObject()的第一个参数的“color”为“colo”,程序运行时将会报错,这时第三个参数就派上用场了,且看错误提示如下:
Error: Qt.createQmlObject(): failed to create object:
qrc:///dynamicSnippet:1:33: Cannot assign to non-existent property "colo"

这里共列举了动态组件创建与销毁的四种方法,实际使用过程中可按需选择。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: