QML概念及框架--QML动态对象管理

来源:互联网 发布:mysql 存储图片base64 编辑:程序博客网 时间:2024/04/29 16:47

    QML提供了很多方法来动态创建和管理QML对象。如Loader、RePeater、ListView、GridView和PathView等元素都支持动态对象管理。对象也可以在C++中被创建和管理,这是混合QML/C++应用程序的首选方式。QML也支持在JavaScript代码中动态创建对象,这在现有的QML元素不适合应用程序需要的情况下是很有用的,而且也不需要涉及C++组件。

1. 动态创建对象

    这里有两种方法从JavaScript动态创建对象。既可以调用Qt.createComponent()来动态创建Compont对象,也可以使用Qt.createQmlObject()从QML字符串来创建对象。如果已经有一个在.qml文件中定义的组件,而且希望冬天创建该组件的一个实例,那么使用第一种方法是比较好的;如果QML本身是在运行时产生的,那么使用QML字符串来创建对象是很有用的。

    (1) 动态创建一个组件

    要动态加载定义在一个QML文件中的组件,可以在QML全局对象上调用Qt.createComponent()函数。这个函数需要将QML文件的URL作为其参数,然后这个URL上创建一个Component对象。一旦有了一个Component,就可以调用它的createObject()函数来创建该组件的一个实例。这个函数需要指定新对象的父对象。因为图形项目没有父对象是无法显示在场景上的,所以建议这样来设置父对象。然而,如果像稍后再为其设置父对象,可以安全的设置null作为该函数的参数。

    QML组件Sprite.qml

import QtQuick 2.4Rectangle { width: 80; height: 50; color: "red" }
  导入JavaScript文件componentCreation.js来创建Sprite对象:
import QtQuick 2.4import "componentCreation.js" as MyScriptRectangle {    id: appWindow    width: 300; height: 300    Component.onCompleted: MyScript.createSpriteObjects()

    componentCreation.js文件,其中在调用createObject()以前检查了组件的状态是否为Component.Ready,因为如果QML文件是从网络上加载的,那么它不会立即可用:

var component;var sprite;function createSpriteObjects() {    component = Qt.createComponent("Sprite.qml")    if(component.status == Component.Ready)        finishCreation();    else        component.statusChanged.connect(finishCreation);}function finishCreation() {    if(component.status == Component.Ready) {        sprite = component.createObject(appWidow)        if(sprite == null) {            //错误处理        } else {            sprite.x = 100            sprite.y = 100            //...        }    } else if(componet.status == Component.Error) {        //错误处理        console.log("Error loading component:", component.errorString())    }}
    如果可以确保QML文件是从本地文件加载的,那么可以忽略finishCreation()函数,而在createSpriteObject()函数中立即调用createObject()函数,上面的可以写成

function createSpriteObjects() {    component Qt.createComponent("Sprite.qml")    sprite = component.createObject(appWindow)    if(sprite == null) {        //Erro Handling        console.log("Erro creating object");    } else {        sprite.x = 100        sprite.y = 100        //...    }}

    注意,这里createObject()使用appWindow作为参数,所以创建的对象会成为main.qml中appWindow的子对象。当使用相对路径来加载文件时,需要是相对于执行Qt.createComponent()的文件的路径。将信号关联到 动态创建的对象上,或者从动态创建的对象上接收信号,都要使用信号的connect()函数。

    (2) 从QML字符串创建一个对象

    如果QML直到运行时才被定义,可以使用Qt.createQmlObject()函数从一个QML字符串创建一个QML对象。

var newObject = Qt.createQmlObject(    'import QtQuick 2.4; Rectangle{color: "red"; width: 20; height:20}', parentItem, "dynamicSnippet1");
    第一个参数是要创建的QML字符串,就像一个新的文件一样,需要导入所需要的类型;第二个参数是父对象,需要在场景中已经存在的一个对象;第三个参数是于新对象相关文件的路径,用来报告错误。如果在QML字符串中导入的文件使用的是相对路径,那么需要相对于定义父对象的文件的路径。

2. 文虎动态创建的对象

   当管理动态创建的对象是,必须确保创建上下文(creation context)不会再创建的对象销毁前被销毁。否则,如果创建上下文被首先销毁,那么在动态创建对象中的绑定将不会再工作。实际的创建上下文依赖于对象是怎样被创建的:

    a.  如果使用了Qt.createComponent(),创建上下文就是调用该函数的QDeclarativeContext;

    b. 如果使用了Qt.crateQmlObject(),创建上下文就是父对象的上下文

    c. 如果定义了一个Component{},然后在其上调用了createObject(),创建上下文就是该Component中定义的上下文

    另外需注意,虽然动态创建的对象可以像其他对象一样来使用,但是它们没有id值。

3. 动态删除对象

    在很多用户界面中,将图形项的透明度设置为0或者将其移除屏幕就够了,而不需要将其删除。然而,如果有很多动态生成的对象,难么将不用的对象删除会得到一个很大的性能提升。不过应该注意,永远不要手动删除通过QML元素(例如Loader和Repeater)动态生成的对象,不要删除不是自己动态创建的对象。

    可以使用destroy()函数来删除对象,这个函数有一个可选参数,可以用来设置在销毁该对象以前的以毫秒为单位的延迟时间,该参数默认为0.在下面列子中,application.qml中创建了SelfDestroyingRect.qml组件的5个实例,每一个实例运行一个NumberAnimation,当动画结束时在其根对象上调用destroy()来进行自我销毁。

    application.qml文件:

import QtQuick 2.4Item {    id: container    width: 500; height: 100    Component.onCompleted: {        var component = Qt.createComponent("SelfDestroyingRect.qml")        for(var i = 0; i < 5; i++) {            var object = component.createObject(container)            object.x = (object.width + 10) * i        }    }}
    SelfDestroyingRect.qml文件

import QtQuick 2.0<pre name="code" class="html">Item {    SelfDestroyingRect{...}}

Rectangle { id: rect width: 80; height: 80 color: "red" NumberAnimation on opacity { to: 0 duration: 1000 onRunningChanged: { if(! runnig) { console.log("Destroying ...") rect.destroy(); } } }}

    另外,application.qml可以调用object.destroy()类销毁创建的对象。在一个对象内部调用destroy()来销毁自己是安全的。对象不会再destroy()被调用时就被销毁,耳屎在该脚本块的末尾和下一帧之间的某个时间进行清理(除非将延时指定了一个非零值)。

     注意,如果SelfDestroyRect实例被静态的创建

Item {    SelfDestroyingRect{...}}
   这样会产生错误,只有动态创建的对象才可以被动态删除。使用Qt.createQmlObject()创建的对象可以相似的使用destroy()来删除

 var newObject = Qt.createQmlObject(        'import QtQuick 2.4; Rectangle {color: "red"; width: 20; height:20}',        parentItem, "dynamicSnippet1"    );    newObject.destroy(1000)






0 0
原创粉丝点击