目录
动态创建qml对象
Qt.createComponent
Qt.createQmlObject
Component qml type
销毁动态创建的对象
QQmlContext
总结
var component = Qt.createComponent()⇒ component.createObject⇒QmlContext是createComponent方法被调用的qml对象的context
qml对象的文件定义:
//DynamicQml.qml import QtQuick 2.0 Rectangle { anchors.fill: parent Image { id: image source: "qrc:/bg.png" } }
主程序的qml中动态创建这个qml对象:
var component = Qt.createComponent("qrc:/DynamicQml.qml") //加载本地的qml文件,所以没有检查component加载状态。 var obj = component.createObject()
createObject()可以输入两个参数,第一个参数指定了生成的对象依附于哪个父亲对象,如果父亲对象是界面对象,那么动态创建的对象可以被描绘。当然我们在创建是也可以不指定,在对象创建成功后通过设置对象的parent来指定。第二个参数指定初始化哪些属性,在对象创建后设置属性也可以,但是通过参数的方式设置有更好的执行效率。下面简单演示下如何传递这两个参数。
//DynamicQml.qml import QtQuick 2.0 Rectangle { anchors.fill: parent property string name: "default name" Image { id: image source: "qrc:/bg.png" } } //main.qml var component = Qt.createComponent("qrc:/DynamicQml.qml") //通过参数的方式设置parent object 和属性值 //加载本地的qml文件,所以没有检查component加载状态。 var obj = component.createObject(rootItem,{name:"init name"}) //通过简单的赋值方式 obj.parent = rootItem obj.name = "init name"
var newObject = Qt.createQmlObject('import QtQuick 2.0; Rectangle {color: "red"; width: 20; height: 20}', parentItem, "dynamicSnippet1");
createQmlObject()方法可以通过加载qml string来创建qml对象,与createObject()不同,它在调用时必须指定parent item。
//main.qml Component{ id:dynamicComponent Rectangle { anchors.fill: parent property string name: "default name" Image { id: image source: "qrc:/bg.png" } Text { id: te text: name anchors.centerIn: parent } } } function(){ var obj = dynamicComponent.createObject(container,{name:"init name"}) }
这里通过在main.qml 文件中定义Component的方式声明了组建,然后通过Component id直接调用createObject()。这里调用createObject时参数的规则与第一种动态创建的规则是一样的。
动态创建的对象需要在不使用的时候销毁掉,否则会造成内存泄漏的问题。我们可以通过调用obj.destroy()方法来释放对象,这个方法不是同步方法,方法被调用后再后面的某一个时间会进行真正的释放,这个方法被调用时,我们也可以指定延时释放的时间。由于释放操作是异步的,所以在对象内部也可以调用自己的destroy方法。destroy调用的时机包括如下:
这里有几个问题需要注意:
QQmlContext与动态创建和销毁qml对象有什么关系呢?其实我们在通过上面介绍的方式创建动态对象时,系统都会为每个动态对象绑定一个QQmlContext对象。QQmlContext对象也是按照树形模型管理的,与QObject的管理方式相同。但是QQmlContext树与QObject树是完全不同的两个树。
当我们调用destroy方法释放对象时,系统通过对象的QQmlContext树来查找分支与叶子QQmlContext并将调用它们绑定的QObject 的destroy方法。destroy方法可以沿着QQmlContext树向下传导调用,所以在动态创建qml对象时,我们还需要关系QQmlContext树的建立,进而保证自己的对象不被意外释放而导致问题。
由于我们创建动态qml对象时,系统会自动生成与之关联的QQmlContext对象,所以我们弄清这个对象的父亲QQmlContext对象是谁,以及如何修改父亲QQmlContext对象就可以控制QQmlContext树的构建了。下面针对上面介绍的三种创建方式分别说明。
根据上面罗列的规则我们可以总结如下:
qml的核心概念就是对象树,通过qml以声明的方式定义了对象树的结构。对象树的关系可以通过设置对象的parent方式而改变。在qml中声明的对象是不能被释放的,只有通过动态创建的qml对象才可以通过调用destroy方法释放。destroy释放的过程是向下传导的,这里的向下传导不是根据对象树结构传导,而是按照QQmlContext的对象树结构向下传导。
通过qml方式声明对象树结构并且没有通过修改parent的方式改变对象树结构,这时对象树与QQmlContext对象树结构是一致的。当我们修改了某些对象的parent或是通过动态创建的方式添加新的qml对象到对象树时,对象树与QQmlContext对象树结构就不同了。所以在使用动态创建qml对象的过程中,我们需要更多地关系QQmlContext对象树的结构变化,进而能游刃有余地管理动态创建的qml对象。