0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在JavaScript中动态的创建QML对象

工程师邓生 来源:嵌入式小生 作者:iriczhao 2022-09-01 10:42 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在实际QML应用开发中,我们可以在JavaScript中动态的创建QML对象。这样做可以延迟对象的实例化,当我们在需要创建对象的时候才在JavaScript代码中创建,则可以缩短应用程序的启动时间,还可以动态创建可视对象,有助于提高应用程序性能。

创建动态对象

有两种方法可以在JavaScript代码中动态的创建对象。

第一种是:调用Qt.createComponent()来动态创建一个Component对象;

第二种是:使用Qt.createQmlObject()函数,以QML字符串的方式创建一个对象。

如果我们已经在QML文档中定义了一个现有组件,并希望可以动态地创建该组件实例,那么可选择第一种方法。当我们需要在运行时创建QML对象,应选择第二种方法。

下文将分别介绍这两种方法。

动态创建组件

要动态加载定义在QML文件中的组件,需调用Qt对象中的Qt.createcomponent()函数。这个函数将接收QML文件的URL参数,并根据这个URL创建一个Component对象。

一旦创建了组件,则可以调用createObject()方法来创建该组件的一个实例。createObject()函数可以接收两个参数:

(1)参数一:第一个是新对象的父对象。父对象可以是图形对象(即Item类型)或非图形对象(即QtObject或C++ QObject类型)。只有带有图形父对象的图形对象才会呈现到Qt Quick视觉画布中。如果想在后续设置父函数,我们可以将null传递给这个函数。

(2)参数二:第二个是可选参数,是<属性-值>的映射,用于定义对象的初始属性值。在创建对象之前,将此参数指定的属性值应用于对象,可以避免绑定错误。当然与在创建对象后定义属性值和属性绑定相比,这种方式在性能上有一些小的影响。

例如,这里有一个qml文件,名为MyComponent.qml,代表一个QML组件:

importQtQuick2.0

Rectangle{width:80;height:50;color:"red"}

然后创建一个JavaScript脚本文件:componentCreation.js。用于检测在调用createObject()之前组件是否被创建好(如果QML文件是通过网络加载的,则不可能立即就准备好,故此处需要判断处理),如下代码:

varcomponent;
varsprite;

functioncreateSpriteObjects(){
component=Qt.createComponent("MyComponent.qml");
if(component.status==Component.Ready)
finishCreation();
else
component.statusChanged.connect(finishCreation);
}

functionfinishCreation(){
if(component.status==Component.Ready){
sprite=component.createObject(appWindow,{x:100,y:100});
if(sprite==null){
//ErrorHandling
console.log("Errorcreatingobject");
}
}elseif(component.status==Component.Error){
//ErrorHandling
console.log("Errorloadingcomponent:",component.errorString());
}
}

在实际的开发中,基本上都是从本地加载qml文件,这时候则可以省略finishCreation()函数,立即调用createObject(),例如下例代码:

functioncreateSpriteObjects(){
component=Qt.createComponent("Sprite.qml");
sprite=component.createObject(appWindow,{x:100,y:100});

if(sprite==null){
//ErrorHandling
console.log("Errorcreatingobject");
}
}

注意,上面例子中,createObject()都是在appWindow作为父参数传递的情况下调用的,因为动态创建的对象是一个可视化对象。创建的对象将成为main.qml中的appWindow对象的子对象,并出现在界面中。

接着我们在main.qml文件中使用import "componentCreation.js" as MyScript语句导入componentcreate.js文件,用于创建MyComponent对象:

importQtQuick2.0
import"componentCreation.js"asMyScript

Rectangle{
id:appWindow
width:300;height:300

Component.onCompleted:MyScript.createSpriteObjects();
}

如果需要将信号连接到动态创建对象的信号处理函数,需使用信号的connect()方法。

以QML字符串形式创建对象

在QML开发中,很多时候都会在运行时定义QML对象,这时候则可以使用Qt.createQmlObject()函数来实现,在函数中指定QML字符串来创建一个QML对象,如下代码:

varnewObject=Qt.createQmlObject('importQtQuick2.0;Rectangle{color:"red";width:20;height:20}',parentItem,"dynamicSnippet1");

Qt.createQmlObject()函数需要三个参数:

(1)第一个参数是要创建的QML字符串。其中的QML字符串就像在新qml文件中创建组件的编写方式一样。

(2)第二个参数是新对象的父对象。

(3)第三个参数是与新对象相关联的文件路径,用于报告错误信息。

【特别注意(一)】

如果QML字符串使用相对路径方式导入文件,则该路径应该相对于父对象(方法的第二个参数)所在的文件。

【特别注意(二)】

在构建静态QML应用程序时,QML引擎会扫描QML文件来检测导入依赖项。这样,所有必需的插件和资源都在编译时解析。但是,只考虑显式的import语句(在QML文件顶部找到的那些),而不会考虑包含在字符串文本中的import语句。因此,为了支持静态构建,我们需要在使用Qt.createQmlObject()的QML文件中,还需要在文件顶部显式地包含所有的导入信息。

管理动态创建的对象

在管理动态创建的对象时,必须确保创建上下文的生命周期比创建的对象长。否则,如果创建上下文先被销毁,动态对象中的绑定和信号处理程序将会“罢工”。

实际的创建上下文取决于对象是如何创建的:

(1)如果使用了Qt.createComponent(),创建上下文就是在其中调用此方法的QQmlContext。

(2)如果调用Qt.createQmlObject(),创建上下文是传递给该方法的父对象的上下文。

(3)如果定义了一个Component{}对象,并且在该对象上调用了createObject()或incubateObject(),那么创建上下文就是组件定义的上下文。

备注:虽然动态创建的对象可以像其他对象一样使用,但它们在QML中是没有id属性的。

删除动态对象

在大多数用户界面开发中,将可视对象的不透明度设置为0或将可视对象移出屏幕,则可以满足许多的开发需求了。但是,如果应用界面中有多个动态创建的对象,那么删除不使用的对象可能会获得较好性能。

但注意不要手动删除由QML对象工厂(如Loader和Repeater)动态创建的对象。另外还应该避免删除不是自己动态创建的对象。

我们可以使用destroy()方法删除Item。该方法有一个可选参数(默认为0),用于指定对象被销毁前的延迟时间。

这里有一个例子:我们在application.qml文件中创建了SelfDestroyingRect的五个实例组件。每个实例运行一个NumberAnimation,当animation完成时,调用它的根对象的destroy()来销毁,代码如下:

//application.qml

importQtQuick2.0

Item{
id:container
width:500;height:100

Component.onCompleted:{
varcomponent=Qt.createComponent("SelfDestroyingRect.qml");
for(vari=0;i<5; i++) {
            var object = component.createObject(container);
            object.x = (object.width + 10) * i;
        }
    }
}

//SelfDestroyingRect.qml

importQtQuick2.0

Rectangle{
id:rect
width:80;height:80
color:"red"

NumberAnimationonopacity{
to:0
duration:1000

onRunningChanged:{
if(!running){
console.log("Destroying...")
rect.destroy();
}
}
}
}

另外,application.qml可以调用object.destroy()来销毁已创建的对象。

备注:上述代码中,调用对象的destroy()是安全的。因为对象不会在调用destroy()的瞬间被销毁,而是在脚本块结束后的某个时刻被清除(非零延迟除外)。

在销毁对象时,需要注意对象只有在动态创建的情况下才能动态销毁。

对于使用Qt.createQmlObject()创建的对象也可以使用destroy()销毁,例如下例JavaScript代码:

varnewObject=Qt.createQmlObject('importQtQuick2.0;Rectangle{color:"red";width:20;height:20}',
parentItem,
"dynamicSnippet1");
newObject.destroy(1000);



审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • URL
    URL
    +关注

    关注

    0

    文章

    142

    浏览量

    16310
  • JAVA语言
    +关注

    关注

    0

    文章

    138

    浏览量

    21708
  • javascript
    +关注

    关注

    0

    文章

    526

    浏览量

    56606

原文标题:“神级”般的QML开发技巧,学会了

文章出处:【微信号:嵌入式小生,微信公众号:嵌入式小生】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    惠州雷曼入选国家知识产权示范企业创建对象

    近日,国家知识产权局正式公布了2025-2027年度国家知识产权强国建设示范创建对象名单。雷曼光电全资子公司——惠州雷曼,凭借其知识产权创造、运用、保护和管理方面的体系化优势,成功入选“国家知识产权示范企业
    的头像 发表于 03-03 16:36 1151次阅读

    鸿利智汇成功入选国家知识产权示范企业创建对象

    近日,国家知识产权局公示了2025—2027年知识产权强国建设示范创建对象名单,鸿利智汇集团股份有限公司入选“国家知识产权示范企业创建对象”。此次入选,标志着国家层面对鸿利智汇知识产权
    的头像 发表于 02-09 14:13 718次阅读

    德州仪器LM117QML/LM117QML - SP可调稳压器深度解析

    德州仪器LM117QML/LM117QML - SP可调稳压器深度解析 电子工程领域,稳压器是电源设计不可或缺的组件,它能够为电路提供稳定的电压输出,确保系统的正常运行。德州仪器(
    的头像 发表于 02-06 11:30 525次阅读

    深入解析LM2941QML与LM2941QML - SP:1A低压差可调稳压器的卓越之选

    深入解析LM2941QML与LM2941QML - SP:1A低压差可调稳压器的卓越之选 电子工程师的日常设计工作,稳压器是不可或缺的重要组件。今天,我们将深入探讨德州仪器(TI
    的头像 发表于 02-05 17:15 890次阅读

    LM2941QML与LM2941QML - SP:1A低压差可调稳压器详解

    LM2941QML与LM2941QML - SP:1A低压差可调稳压器详解 电子设计领域,稳压器是不可或缺的组件,它能为电路提供稳定的电压,保证电子设备的正常运行。今天我们就来详细探讨德州仪器
    的头像 发表于 02-05 17:15 805次阅读

    深入剖析LM2940QML与LM2940QML - SP 1A低压差稳压器

    和LM2940QML - SP这两款1A低压差稳压器,看看它们有何独特之处,以及实际设计如何更好地应用。 文件下载: lm2940qml.pdf 一、产品特性亮点 辐射特性 :这两
    的头像 发表于 02-05 13:50 581次阅读

    罗莱迪思入选国家知识产权示范企业创建对象

    近日,国家知识产权局正式公示了2025—2027年知识产权强国建设示范创建对象评审结果,杭州数智光科技“小龙”罗莱迪思凭借知识产权领域的深厚积淀与实力成功入选国家知识产权示范企业创建
    的头像 发表于 01-27 16:06 1008次阅读
    罗莱迪思入选国家知识产权示范企业<b class='flag-5'>创建</b><b class='flag-5'>对象</b>

    芯原入选国家知识产权示范企业创建对象

    1月12日,国家知识产权局公示了“2025-2027年国家知识产权强国建设示范创建对象”的评审结果,芯原微电子 (上海) 股份有限公司凭借其知识产权创造、运用、管理和保护方面的扎实基础与突出成效,成功入选“国家知识产权示范企业
    的头像 发表于 01-27 15:28 410次阅读

    度亘核芯成功入选“国家知识产权示范企业创建对象

    近日,国家知识产权局正式公布2025-2027年新一批知识产权强国建设示范企业创建对象名单,度亘凭借知识产权创造、运用、保护、管理全链条的卓越表现成功入选。这一国家级荣誉的加持,既是对公司深耕创新
    的头像 发表于 01-21 17:31 1569次阅读
    度亘核芯成功入选“国家知识产权示范企业<b class='flag-5'>创建</b><b class='flag-5'>对象</b>”

    RTThread线程退出后rt_malloc动态创建的资源没有释放怎么解决?

    测试过程一个线程中用rt_malloc动态创建4KB的资源,在线程运行过程中用rt_thread_delete()使线程退出,用memtrace查看内存分配情况,
    发表于 10-13 07:06

    RT-Thread Nano移植后动态创建线程创建不了怎么解决?

    RT-Thread Nano 移植后动态创建线程创建不了,静态可以.直接烧录DEMO也一样,将RT_USING_HEAP开起来,使用动态创建
    发表于 09-19 06:28

    rtth studionano 如何创建动态线程?

    有没有大佬,可以说一下为什么静态线程可以正常使用,动态线程怎么也使用不了。 具体需要什么配置才能使用动态线程创建。谢谢!
    发表于 09-11 06:01

    rtt studionano 如何创建动态线程?

    有没有大佬,可以说一下为什么静态线程可以正常使用,动态线程怎么也使用不了。 具体需要什么配置才能使用动态线程创建。谢谢!
    发表于 08-22 06:19

    ‌LM136A-2.5QML/LM136A-2.5QML-SP 技术文档摘要

    LM136A-2.5QML集成电路是一款精密的2.5V并联稳压二极管。该单片IC基准电压源作为低温度系数的2.5V齐纳管工作,动态阻抗为0.2Ω。LM136A-2.5QML 上的第三个端子可以轻松
    的头像 发表于 08-15 09:55 1269次阅读
    ‌LM136A-2.5<b class='flag-5'>QML</b>/LM136A-2.5<b class='flag-5'>QML</b>-SP 技术文档摘要

    RT-Thread Nano移植后动态创建线程创建不了怎么处理?

    RT-Thread Nano移植后动态创建线程创建不了,静态可以.直接烧录DEMO也一样,将RT_USING_HEAP开起来,使用动态创建
    发表于 06-11 06:36