QML如何创建动态组件

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"

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

时间: 2024-10-09 13:13:14

QML如何创建动态组件的相关文章

Angular 动态组件

Angular 动态组件 实现步骤 Directive HostComponent 动态组件 AdService 配置AppModule 需要了解的概念 Directive 我们需要一个Directive来标记动态组件是在哪个容器组件内部进行渲染的. 这个Directive可以获取对容器组件的引用. 仅此而已. import { Directive, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[appAd]'

Vue动态组件&异步组件

在动态组件上使用keep-alive 我们之前曾经在一个多标签的界面中使用is特性来切换不同的组件: <component v-bind:is="currentTabComponent"></component> 当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题. 如上是vue官网的例子,你会注意到如果你选择一篇文章,切换到Archive标签,然后切回Posts, 是不会继续展示你之前选择的文章的.因为你每次切换新标签的时

RobotStudio Smart组件创建动态夹具

一.创建动态夹具的smart组件 二.添加组件 ☆Attacher-安装一个对象 属性:Parent-安装的父对象 Flange:机械装置或工具数据安装到 Child:安装对象 Mount:移动对象到其父对象 Offset:当进行安装时位置与安装的父对象相对应 Orientation:当进行安装时,方向与安装的父对象相对应 输入:Execute:设为high(1)时去安装 输出:Executed:设为high(1)时当此操作完成 ☆Detacher-拆装一个已安装的对象 属性:Child:安装对

0810 vue 创建组件 模板 动态组件 传值

lesson10 1.demo    vue样本 <body> <div id="myApp"> </div> </body> <script> new Vue({ el:"#myApp", data:{}, methods:{}, computed:{}, filters:{} }) </script> 2.案例: 模拟百度搜索框 <!DOCTYPE html> <html

【REACT NATIVE 系列教程之二】创建自定义组件&&导入与使用示例

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/react-native/2219.html 在上一篇  [REACT NATIVE 系列教程之一]触摸事件的两种形式与四种TOUCHABLE组件详解 中的最后介绍了如何使用Touchable的四种组件进行监听触摸事件.  那么紧接着我们利用Touchable来包装一个带图片的Button组件,且设计成可接受很多自定义参数. 一:创建我们自定义

angular2 学习笔记 ( Dynamic Component 动态组件)

一样这一篇最要讲概念而已. refer : http://blog.rangle.io/dynamically-creating-components-with-angular-2/ (例子)https://www.ag-grid.com/ag-grid-angular-aot-dynamic-components/ (动态 entryComponents) http://stackoverflow.com/questions/40106480/what-are-projectable-node

Hibernate学习---第五节:普通组件和动态组件

一.普通组件映射配置 1.创建组件类,代码如下: package learn.hibernate.bean; /** * 组件类 */ public class Phones { private String companyPhone; private String homePhone; private String personalPhone; public Phones() { } public Phones(String companyPhone, String homePhone, St

vue2入坑随记(二) -- 自定义动态组件

学习了Vue全家桶和一些UI基本够用了,但是用元素的方式使用组件还是不够灵活,比如我们需要通过js代码直接调用组件,而不是每次在页面上通过属性去控制组件的表现.下面讲一下如何定义动态组件. Vue.extend 思路就是拿到组件的构造函数,这样我们就可以new了.而Vue.extend可以做到:https://cn.vuejs.org/v2/api/#Vue-extend // 创建构造器 var Profile = Vue.extend({ template: '<p>{{firstName

C++ 类的动态组件化技术

序言: N年前,我们曾在软件开发上出现了这样的困惑,用VC开发COM组件过于复杂,用VB开发COM组件发现效率低,而且不能实现面向对象的很多特性,例如,继承,多态等.更况且如何快速封装利用历史遗留的大量C++代码本身就是一个大的难题. 当时,开发小组的成员通过共同努力,摸索了一套C++类的动态组件化技术,很好的解决了以上的问题,通过这个技术,我们继承了大量的C++代码,同时使这些C++程序以COM+组件的形式得以新生.通过这几年在实际应用中的考验,这个技术是成熟可靠的. 也许新的系统大多数都完全