QML学习笔记(二十)QML的自定义信号
前言
此前我们一直都在使用Qt系统生成的信号,比如MouseArea的clicked信号,这些都默认内置在Qt中。而本小节中将学习如何实现我们自己的自定义信号。
一、自定义信号
想要使用自定义信号,我们先要做的就是定义它。
这里我们使用siganl来定义,并且可以设置自己想传递的参数
signal greet(string message)
我们可以实现这个信号的处理器,这非常简单:
onGreet: message => {console.log("Greeting with message: " + message)
}
最后,我们在MouseArea的clicked中,像调用接口一样调用这个信号:
MouseArea{anchors.fill: parentonClicked: {rectId.greet("The sky is blue")}}
运行程序,单击矩形,观察打印信息:
可以看到,我们发送信号时指定的字符串,已经传递到其处理器内部的打印信息中,运行结果符合预期。
二、将自定义信号连接到方法
然而,如果自定义信号只能在on的处理器中实现,未免也太有局限性了。我们期望它能有QWidget那种信号槽的绑定,事实上qml也确实有这种方式。
相对于槽函数的,我们先设置一个自定义的函数,但要注意其所在的组件。
我先在rectId中定义,然后我在Window的最后实现附加处理器代码,在里面通过connect来实现绑定:
import QtQuick 2.14
import QtQuick.Window 2.14Window {id: windowIdvisible: truewidth: 640height: 480title: qsTr("Qml Custom Signals")Rectangle{id: rectIdwidth: 300height: 300color: "dodgerblue"signal greet(string message)onGreet: message => {console.log("Greeting with message: " + message)}MouseArea{anchors.fill: parentonClicked: {rectId.greet("The sky is blue")}}function respand_your_way(message){console.log("Responding our way;Greeting with message: " + message)}}Component.onCompleted: {rectId.greet.connect(rectId.respand_your_way)}
}
我们注意这句rectId.greet.connect(rectId.respand_your_way),它和QWidget中的connect有写法上的区别,但本质上是相同的。连接信号和槽的时候,我们需要指定发送对象、信号、接受对象、槽函数,因此这里的rectId非常关键,实际上我们可以连接不同组件的信号和槽。
让我们在Window组件中实现槽函数,并进行绑定:
function respand_your_way_1(message){console.log("Responding our way;Greeting with message: " + message)}Component.onCompleted: {
// rectId.greet.connect(rectId.respand_your_way)
// rectId.greet.connect(respand_your_way_1)rectId.greet.connect(windowId.respand_your_way_1)}
运行结果也是没有问题的。这里可以指定windowId,也可以不填,不填的话就是默认当前组件,同样可以找到该函数入口。
三、将自定义信号连接到信号
信号可以连接到槽,也可以连接到信号,这样就可以实现一长串的信号触发链。
写法和上一步差不多,只不过链接的不是函数,而是信号而已。
import QtQuick 2.14
import QtQuick.Window 2.14Window {id: windowIdvisible: truewidth: 640height: 480title: qsTr("Qml Custom Signals")Rectangle{id: rectIdwidth: 300height: 300color: "dodgerblue"signal greet(string message)signal forward_greeting(string message)function respand_your_way(message){console.log("Responding our way;Greeting with message: " + message)}MouseArea{anchors.fill: parentonClicked: {rectId.greet("The sky is blue!")}}Component.onCompleted: {rectId.greet.connect(rectId.forward_greeting)rectId.forward_greeting.connect(rectId.respand_your_way)}}
}
可以看到,两个信号进行了连接:
rectId.greet.connect(rectId.forward_greeting)
第二个信号绑定的函数:
rectId.forward_greeting.connect(rectId.respand_your_way)
结果鼠标点击后,触发的是第一个信号:
rectId.greet("The sky is blue!")
消息依旧能传递到函数中:
这种信号连接的写法还挺常见和实用的的,而且也足够简单。
四、总结
本节我们学习了自定义信号,并且学习了信号连接到槽函数、信号连接到信号的方法。
前几章我们一直用处理器来描述,但实际上就应该理解为槽(Slot),或槽函数,这种说法都是对的,你不需要对此感到困惑。
有了自定义信号,组件间的通知和交互将变得方便,也可以实现更多复杂有趣的功能。