QML学习笔记(十七)QML的属性变更信号
前言
如果你已经比较熟悉QWidget,那你应该对信号的概念不会陌生。一般来说我想要用自定义的信号,都是需要进行单独定义的,即在该类的头文件中进行定义,该类还必须设置了Q_OBJECT这个宏定义,不然无法使用信号槽机制。
而在QML中的信号机制与之有些不同。比较特殊的一个就是属性变更信号,对于QML组件来说,你定义的任何属性,它都会给你设置一个信号,这个信号名称将采用on<属性名>Changed的格式。
这一点,其实在之前的学习中也简单应用过。让我们深入体验以下。
一、了解属性变更信号
width是一个十分常见的属性,而onWidthChanged就是与之对应的变更信号。
注意,这些信号是为了属性而生成的,不是为了信号而生成的。
我们熟悉的onClicked是一个处理器,它对应的信号是clicked,而clicked是鼠标单击时触发的信号,它不是一个属性。至于为什么会存在这个信号,不在本节的讨论范围内。
我们需要对这些概念有清晰的认知,切记不要混淆了。
我们新增一个工程QmlPropertyChangeHandler。
代码如下:
import QtQuick 2.14
import QtQuick.Window 2.14Window {visible: truewidth: 640height: 480title: qsTr("Property changed handers")Rectangle {id: rectIdwidth: 300height: width +50color: "dodgerblue"// 已有属性的变更信号处理器onWidthChanged: {console.log("Width change to: " + rectId.width)}onHeightChanged: {console.log("Height change to: " + rectId.height)}onColorChanged: {console.log("Color change to: " + rectId.color)}// 自定义属性property string descritption: "abcdefg"// 该属性的变更信号处理器onDescritptionChanged: {console.log("Descritption change to: " + rectId.descritption)}}}
我们实现了一些已有属性的变更信号处理器,也设置了自定义属性descritption和其变更信号处理器。这里特别说一下,不只是int和string这种类型才可以触发变更信号,像color这种也可以。
最后,我们设置一下鼠标点击的代码,修改这些属性:
MouseArea{anchors.fill: parent// 鼠标点击时,修改矩形宽度和描述onClicked: {rectId.width += 20rectId.descritption = "New data"rectId.color = "Orange"}}
二、观察打印信息
运行代码,发现此时已经有一条打印了。
明明我都还没按下鼠标,为什会有这一条呢?
原因是矩形的height值是和width进行了属性绑定的,当初始化width的时候,也就意味着对height进行了修改,自然就会触发这里的变更信号处理器。这一点我们要有灵敏的察觉,不然以后可能会导致奇怪的为题。
然后我们点击按钮,观察现象:
可以看到,这些打印信息都被打印悉数出来了,并且是根据我们代码的顺序来触发的,矩形的颜色也得到了更改。
三、QML中信号机制的触发顺序
到这里,其实本节的学习就结束了。可我突然有个疑问,在QML中这样的一种信号槽,它的触发顺序到底是怎样的呢?于是我稍作修改了一下:
MouseArea{anchors.fill: parent// 鼠标点击时,修改矩形宽度和描述onClicked: {console.log("1")rectId.width += 20console.log("2")rectId.descritption = "New data"console.log("3")rectId.color = "Orange"console.log("4")}}
结果我发现打印信息变成了:
qml: Height change to: 350
qml: 1
qml: Width change to: 320
qml: Height change to: 370
qml: 2
qml: Descritption change to: New data
qml: 3
qml: Color change to: #ffa500
qml: 4
这意味着,这里使用的属性变更处理器就是同步回调的——这一点也符合Qt中对于信号槽机制的定义:同一线程中的信号槽,默认是同步触发的。
四、总结
这节的内容也比较简单好懂,但属性变更信号和其处理器这个机制,在传统QWidget中应该是没有的。如果你想要监听类中的某个变量的变化,那可就没这么方便了。可能要单独设置setX这种接口,内部发送一个信号;又或者设置定时器去检测,总之绝对不可能先本节介绍的这种QML机制方便。