QML的信号与handler机制与Qt信号与槽机制类似。一个对象类型可以定义自己的信号,也可以将信号与某个方法进行连接。
一、信号及handler
在每一个对象类型中都会有一个与信号对应的handler属性,当信号发送时,对应的handler会自动被调用。例如:
Item {
id: myitem
signal errorOccurred)
onErrorOccurred: {console.log("recieved");}
}
在类型声明中,定义了一个信号errorOccurred,QML会自动为对象类型定义一个名为onErrorOccurred的handler。如果希望对errorOccurred信号进行处理,则需要为onErrorOccurred属性指定一个javaScript代码块。当errorOccurred信号被发送时,onErrorOccurred会被自动调用。
每一个属性都具有一个信号,当属性被修改时,这个信号会被自动发送。相应的,每一个属性修改信号都有一个handler,用来接收这个信号。
二、信号参数的接收
信号是可以具有参数的。在定义handler是,需要使用箭头函数或者匿名函数来接收信号传递的参数。以下为一个具有参数的信号及handler实例:
// Status.qml
import QtQuick
Item {
id: myitem
signal errorOccurred(message: string, line: int, column: int)
onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`)
}
handler如果不需要接收所有参数,也可以或略尾部的无关参数。例如:
Status {
onErrorOccurred: function (message) { console.log(message) }
}
如果前面的参数不需要也可以采用占位符的方式进行处理
Status {
onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`)
}
三、信号的连接
通常信号都是通过对象类型内部的handler来接受的,但是也可以在一个对象类型的外部接收信号。可以采用QtQuick模块中的Connections类型的对象对信号进行接收。Connections类型中的Target属性指定了接收哪个对象的信号。以下是一个使用Connections类型对象的实例:
import QtQuick
import QtQuick.Controls
Rectangle {
id: rect
width: 250; height: 250
Button {
id: button
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text: "Change color!"
}
Connections {
target: button
function onClicked() {
rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
}
}
}
在以上实例中 onClicked()函数是button对象clicked信号的handler。
一个信号也可以和一个方法或者一个信号进行连接。每一个信号对象都有一个connect()方法,通过这个方法,可以把一个信号连接到一个方法或者另一个信号上。以下是一个例子:
import QtQuick
Rectangle {
id: relay
signal messageReceived(string person, string notice)
Component.onCompleted: {
relay.messageReceived.connect(sendToPost)
relay.messageReceived.connect(sendToTelegraph)
relay.messageReceived.connect(sendToEmail)
relay.messageReceived("Tom", "Happy Birthday")
}
function sendToPost(person, notice) {
console.log("Sending to post: " + person + ", " + notice)
}
function sendToTelegraph(person, notice) {
console.log("Sending to telegraph: " + person + ", " + notice)
}
function sendToEmail(person, notice) {
console.log("Sending to email: " + person + ", " + notice)
}
}
在这个例子中messageReceived信号被连接到sendToPost方法、sedToTelegraph方法以及sendToEmail方法上。
以下是一个将信号与其他信号连接的实例:
import QtQuick
Rectangle {
id: forwarder
width: 100; height: 100
signal send()
onSend: console.log("Send clicked")
TapHandler {
id: mousearea
anchors.fill: parent
onTapped: console.log("Mouse clicked")
}
Component.onCompleted: {
mousearea.tapped.connect(send)
}
}
当对象被创建后,mousearea的Tapped信号被连接到send信号上。每当mousearea信号的tapped信号被发送,send信号也会被自动发送。