前言
如果你已经比较熟悉QWidget,那你应该对信号的概念不会陌生。一般来说我想要用自定义的信号,都是需要进行单独定义的,即在该类的头文件中进行定义,该类还必须设置了Q_OBJECT这个宏定义,不然无法使用信号槽机制。
而在QML中的信号机制与之有些不同。比较特殊的一个就是属性变更信号,对于QML组件来说,你定义的任何属性,它都会给你设置一个信号,这个信号名称将采用on<属性名>Changed的格式。
这一点,其实在之前的学习中也简单应用过。让我们深入体验以下。
一、了解属性变更信号
width是一个十分常见的属性,而onWidthChanged就是与之对应的变更信号。
注意,这些信号是为了属性而生成的,不是为了信号而生成的。
我们熟悉的onClicked是一个处理器,它对应的信号是clicked,而clicked是鼠标单击时触发的信号,它不是一个属性。至于为什么会存在这个信号,不在本节的讨论范围内。
我们需要对这些概念有清晰的认知,切记不要混淆了。
我们新增一个工程QmlPropertyChangeHandler。
代码如下:
cpp
import QtQuick 2.14
import QtQuick.Window 2.14
Window {
visible: true
width: 640
height: 480
title: qsTr("Property changed handers")
Rectangle {
id: rectId
width: 300
height: width +50
color: "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这种也可以。
最后,我们设置一下鼠标点击的代码,修改这些属性:
cpp
MouseArea{
anchors.fill: parent
// 鼠标点击时,修改矩形宽度和描述
onClicked: {
rectId.width += 20
rectId.descritption = "New data"
rectId.color = "Orange"
}
}
二、观察打印信息
运行代码,发现此时已经有一条打印了。
明明我都还没按下鼠标,为什会有这一条呢?
原因是矩形的height值是和width进行了属性绑定的,当初始化width的时候,也就意味着对height进行了修改,自然就会触发这里的变更信号处理器。这一点我们要有灵敏的察觉,不然以后可能会导致奇怪的为题。
然后我们点击按钮,观察现象:
可以看到,这些打印信息都被打印悉数出来了,并且是根据我们代码的顺序来触发的,矩形的颜色也得到了更改。
三、QML中信号机制的触发顺序
到这里,其实本节的学习就结束了。可我突然有个疑问,在QML中这样的一种信号槽,它的触发顺序到底是怎样的呢?于是我稍作修改了一下:
cpp
MouseArea{
anchors.fill: parent
// 鼠标点击时,修改矩形宽度和描述
onClicked: {
console.log("1")
rectId.width += 20
console.log("2")
rectId.descritption = "New data"
console.log("3")
rectId.color = "Orange"
console.log("4")
}
}
结果我发现打印信息变成了:
cpp
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机制方便。