QML如何创建动态组件

 

2014年12月12日 16:17:39

阅读数:5288

QML动态组件指的是按需分配,需要时我们就创建一个自定义组件,也就是所谓的对象延迟实例化,而不是在程序一开始就创建它,不需要时我们就把它销毁以节约内存,而不是传统意义上的隐藏或覆盖。我们可以使用Component与Loader,也可以使用JavaScript的形式来完成。

 

先来介绍一下Component——

progress属性,加载组件的过程,从0.0到1.0变化。

status属性,加载组件的状态,其枚举值分别是Component.Null/Ready/Loading/Error。

url属性,组件路径。

completed()附加信号,对象实例化完成后触发。

destruction()附加信号,对象开始销毁时触发。

object createObject(Itemparent, object properties)函数,创建对象。

string errorString()函数,错误描述。

object incubateObject(Itemparent, object properties,enumerationmode)函数,通过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(urlsource, object properties)函数,设置预加载组件路径。

 

在同一个QML文件中使用ComponentLoader——

Component可封装我们想要的东西,对外只提供一个定义好的接口,也就是其id属性,然后我们就可以重复使用它了。如果某个QML文件重复使用的Component比较小,或者说Component在逻辑上属于某个QML文件,那么该Component就应该在这个QML文件中定义,此时的Loader用到的就是其sourceComponent属性,如下例子:

 

 
  1. import QtQuick 2.2

  2.  
  3. Rectangle {

  4. width: 360; height: 360

  5. color: "lightblue"

  6.  
  7. MouseArea {

  8. anchors.fill: parent

  9. onClicked: {

  10. loader.sourceComponent = component

  11. loader2.sourceComponent = component

  12. }

  13. }

  14.  
  15. Component {

  16. id: component

  17. Rectangle {

  18. width: 80; height: 80

  19. color: "red"

  20. }

  21. }

  22.  
  23. Loader { id: loader }

  24. Loader {

  25. id: loader2;

  26. anchors.centerIn: parent

  27. onLoaded: item.color = "green"

  28. }

  29. }

 

由于Component不是继承自Item,所以使用anchors锚布局无效,但Loader可以使用。例子中单击鼠标时创建了两个组件,双击鼠标时又把这两个组件销毁了,销毁时需要设置sourceComponent属性值为undefined。

 

组件分离——

QML文件本身也可以是一个Component,这样就与使用它的QML文件分离开了,这样做的好处是该Component可以被多个QML文件使用,代码结构也清晰明了,此时的Loader用到的就是其source属性,如下例子:

 
  1. // comp.qml as a separated Component

  2. import QtQuick 2.2

  3.  
  4. Item {

  5. Row {

  6. spacing: 5

  7. Rectangle {width: 80; height: 80; color: "red" }

  8. Rectangle {width: 80; height: 80; color: "yellow" }

  9. Rectangle {width: 80; height: 80; color: "green" }

  10. }

  11. }

  12.  
  13. // main.qml

  14. import QtQuick 2.2

  15.  
  16. Rectangle {

  17. width: 360; height: 360

  18. color: "lightblue"

  19.  
  20. MouseArea {

  21. anchors.fill: parent

  22. onClicked: {

  23. loader.source = "comp.qml"

  24. loader2.source = "comp.qml"

  25. }

  26. onDoubleClicked: {

  27. loader.source = ""

  28. loader2.source = ""

  29. }

  30. }

  31.  
  32. Loader { id: loader}

  33. Loader { id: loader2; y: 100}

  34. }

例子中单击鼠标时从外部加载了两个组件,双击鼠标时又把这两个组件销毁了,销毁时需要设置source属性值为“”即一个空值。

 

QML文件中创建——

先使用Qt.createComponent(url, mode, parent)从QML文件中创建一个组件,必要时可以根据Component.status属性判断创建状态,然后使用Component.createObject()在某个父对象下实例化对象,最后使用destroy()销毁对象,函数参数可以指定一个时间,单位是毫秒,默认为0,如下例子:

 
  1. import QtQuick 2.2

  2.  
  3. Rectangle {

  4. property var object

  5. property var component

  6.  
  7. width: 360; height: 360

  8. color: "lightblue"

  9.  
  10. MouseArea {

  11. anchors.fill: parent

  12. onPressed: {

  13. component = Qt.createComponent("comp.qml")

  14. if(Component.Ready === component.status) {

  15. object = component.createObject(parent)

  16. }

  17. }

  18. onReleased: {

  19. object.destroy(2000)

  20. }

  21. }

  22. }

例子中按下鼠标时从QML文件中创建了一个组件component并实例化一个对象object,释放鼠标时在2000毫秒后对象object销毁,但组件component还是存在的。

 

QML字符串中创建——

使用Qt.createQmlObject(stringqml, object parent, string filepath)从QML字符串中创建,第一个参数是要创建对象的QML字符串,第二个参数指定要创建对象的父对象,第三个参数用于报告错误,例子如下:

 
  1. import QtQuick 2.2

  2.  
  3. Rectangle {

  4. property var object

  5.  
  6. width: 360; height: 360

  7. color: "lightblue"

  8.  
  9. MouseArea {

  10. anchors.fill: parent

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

  12. onReleased: object.destroy(1000)

  13. }

  14. }

如果修改例子中Qt.creatQmlObject()的第一个参数的“color”为“colo”,程序运行时将会报错,这时第三个参数就派上用场了,且看错误提示如下:

 
  1. Error: Qt.createQmlObject(): failed to create object:

  2. qrc:///dynamicSnippet:1:33: Cannot assign to non-existent property "colo"

 

这里共列举了动态组件创建与销毁的四种方法,实际使用过程中可按需选择。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值