QML 中的默认属性

QML 中的默认属性

在讲默认属性前,先说一说 QML 对象本身具备什么东西。例如属性方法信号

但是如果 QML 对象本身包含了另一个 QML 对象实体,这个对象实体该怎么归纳?

QML 中的 data 链表属性

Item {
    id: root
    width: 100
    height: 100
    Item { 
        id: child
        width: 100
        height: 100
    }
}

上诉代码中,一个 Item 包含了另外一个 Item。这两个 Item 就形成了父子关系。其实就是将 child 归属到了 rootdata 这个链表属性中。

也就是说,QML 对象中,所有的 QML 实体对象都会默认归属到一个链表属性中,并且建立起父子关系(QtObject 除外,Item 及其 C++ 派生类有效,在 QML 中重新设定默认属性的无效)。

QML 中 qmltype 类型的默认属性

qmltype 为包括 var 不定类型,但是不包括 list<T>QtObject 或者 Item 及其派生类型。

如下定义了一个新的 qmltype,并且设定了默认属性的类型是 Item

//~ MyItem.qml
Item {
    default property Item myChild
}

如下代码 childroot 构建起了父子关系。

//~ test1.qml
MyItem {
    id: root
    Item {
        id: child
    }
}

如下代码和上述代码方式类似:

//~ test2.qml
MyItem {
    id: root
    myChild: Item {
        id: child
    }
}

再看看如下代码:

//~ test3.qml
MyItem {
    id: root
    Item {
        id: child0
    }
    Item {
        id: child1
    }
}

出现了两个 Item,此时默认属性是捕获最后一个 child1。但是 child0child1 都和 root 建立起了父子关系。

此外 QML 在构建时会进行类型检查,并允许类型的向上转换,如下代码编译不通过。

MyItem {
    id: root
    QtObject {
        id: child0
    }
}

因为 QtObject 不能转换为 Item

QML 中自定义默认映射链表属性映射到 native 默认链表属性

native 默认链表属性,是指在 c++ 代码中,定义 qmltype 的类中,使用类似 Q_CLASSINFO("DefaultProperty", "data") 声明的某个链表属性。例如 Item::data,在 c++ 代码中,会对加入 dataQObject* 进行父子关系构建Item::data 的类型在 c++ 是 QQmlListProperty<QObject>,在 qml 中的类型是 list<QtObject>

自定义默认映射链表属性是指在 qml 文档中定义的默认属性以引用的方式映射到 native 默认链表属性

先看如下代码:

//~ Container.qml
Item {
    id: container
    default property alias data: content.data
    Item {
        id: content
        anchors.fill: container
        anchors.margins: 10
    }
}

//~ userContainer.qml

Container {
    Rectangle { 
        id: rect
        anchors.fill: parent
    }
}

上诉代码定义了一个新的 qmltype Container ,并将默认链表属性映射为内部 contentdata。在使用 Container 时,这个机制会将所有的 Container 实例化后的所有内部的对象(不包括原本 Container 内部的 content)与 content 建立起父子关系。

这种做法一般用来定制一些有布局关系的控件。例如带有头部、内容区域、底部的 Page 控件。如下提供一个简单的示例代码:

//~ Page.qml
Item {
    id: page
    default property alias data: content.data
    Item {
        id: header
        width: page.width
        height: 10
    }
    Item {
        id: footer
        width: page.width
        height: 10
    }
    Item {
        id: content
        width: page.width
        anchors.top: header.bottom
        anchors.bottom: footer.top
    }
}

//~ userPage.qml
Page {
    Button {}
}

使用时,就可以看到效果,Button 是位于 Page 的内容区域中,而不会在 Page 的头部或者尾部,意味着可以将控件内部的子控件限定在指定的布局中

QML 中自定义默认链表属性

自定义默认链表属性是指形如 default property list<T> defaultProperies 的属性。

先看如下代码:

//~ MyItem.qml
Item {
    default property list<Item> myChildren
}

//~ userMyItem
MyItem {
    Item {}
    Item {}
    Item {}
    Item {}    // parent is null
}

但是这个 MyItem 不会与实例化后的内部对象实体建立起父子关系。怎么办?只能直接手动设置父子关系了。

//~ MyItem.qml
Item {
    id: myItem
    default property list<Item> myChildren
    onMyChildrenChanged: {
        for(var iter in myChildren) { 
            myChildren[iter].parent = myItem;
        }
    }
}

//~ userMyItem
MyItem {
    Item {}
    Item {}
    Item {}
    Item {}
}

这样就可以做到和 native 默认链表属性同样的功能了。


QML Object Attributes

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值