QML 中神秘的 Component
2016-02-28 20:54
302 查看
QML 中神秘的 Component
在 ListView 中有个代理模式,其中最为重要的是名为delegate的属性。
通过设置
delegate以不同的方式,展示数据项。可是你曾发现
ListView::delegate的接口类型为
Component,却不是
Item。
下面通过一些代码为你一一道出 Component 不为人知的秘密
Component 包裹对象的作用域
这里的作用域亦可是可被访问的范围。[code]import QtQuick 2.0 Item { //! [0] id: root Component { //! [1] id: com Text { //! [2] id: label text: "I am Text" //! [2] } //! [1] } Loader { anchors.fill: parent sourceComponent: com } //! [0] }
如上诉代码,其中有三个可访问的标识符:
root,
com,
label。
root在整个
0是可以被访问的,
com访问域也是在整个
0区。但是
label只能在
2区被访问。刚好被
1给包裹了。
其实,
label就是作为
com的模板对象(模板图元),构造对应的对象出来。
Component 和 Loader 的配合
讲完之后。我们再来一次代码看一看。首先我们定义一个Panel,如下:
[code]//~ Panel.qml import QtQuick 2.0 Rectangle { width: 100 height: 100 color: "transparent" border.color: "black" border.width: 1 property Component label Loader { id: loader anchors.fill: parent anchors.margins: parent.width * 0.1 sourceComponent: label } }
这里的
Loader会从
label那里获取到一个模板图元,然后依据这个模板图元进行对象构建,
Loader作为父亲参数调用
label的
object Component::createObject(Item parent, object properties)函数,返回的对象设置给
Loader::item属性。
当
Loader::sourceComponent改变的时候,他会先销毁之前的根据
label构建的对象,然后再重新构建新对象,设置到
Loader::item。
下面是
Loader::setSourceComponent(Component c)的
c++伪码:
[code]void Loader::setSourceComponent(Component c) { if(this.sourceComponent != c) { if(this.item != null) { this.item.deleteLater(); this.item = null; } this.sourceComponent = c; emit this.sourceComponentChanged(); // 信号触发后,就构建新的对象到 this.item } }
Compoent 的自动装箱
测试代码如下:[code]import QtQuick 2.5 Item { width: 640 height: 360 Row { anchors.fill: parent Panel { id: panel1 label: Component { id: greenCom Rectangle { color: "green" Component.onDestruction: { console.log("Green Rectangle Destruction") } } } } Panel { id: panel2 label: Rectangle { color: "red" } } } Component { id: yellowCom Rectangle { color: "yellow" } } MouseArea { anchors.fill: parent onClicked: { panel1.label = yellowCom; if(time == 0) { console.log("set cache only once") cache = panel2.label; } panel2.label = yellowCom; ++time; console.log(cache, cache.progress) } } property int time: 0 property var cache Component.onCompleted: { console.log(panel2.label) } }
其中
panel2的
lable参数不是
Component,但是 Qt 会为其构建一个
Component进行自动封装(不是类型转换,类似 Java 的装箱)。
当你修改
panel2的
lable属性时,跟前面所说的一样,旧的对象会被销毁,并被新的对象替代。同理,
panel1也是。
因为自动装箱而产生的 Component 回收情况
你会注意到,panel2之前自动产生
label对象保存在
cache中,并没有被销毁(访问
progress不报空指针异常)。也就是装箱产生的封装类,不会被马上回收。
由于是 Qt 自动生成的,所以其对象所有权应该属于 QmlEngine,在满足一些条件时会被自动回收。可以尝试使用
ObjectOwnership QQmlEngine::objectOwnership(QObject * object)查询对象的所有权,这里没有进行测试,有空再说啦~
相关文章推荐
- stat查找权限以数字形式显示
- kali2.0 Metasploit连接postgres数据库
- C json实战引擎 二 , 实现构造部分
- (2016.2.28)寒假第三次作业随笔
- ROS launch file 写法
- linux精讲——su切换用户
- 删除事件处理程序如何解决
- ubuntu 系统配置维护 常用命令
- MOOC《Linux内核分析》第一课
- [LeetCode]236 二叉树的最近公共父亲节点
- leetcode笔记:Majority Element II
- 安全卫士第三天
- 导入表
- python常用异常
- 菩提本无树,明镜亦非台。本来无一物,何处惹尘埃.
- uva 10780 素因子分解
- 计算机网络部分基础知识
- 2016成长之路
- Android向通讯录添加联系人的一般方法
- tcp连接断开的一些面试常识