概述
QML 具有信号和处理程序机制,其中信号是事件,信号通过信号处理程序进行响应。
当发出信号时,会调用相应的信号处理程序。在处理程序中放置诸如脚本或其他操作之类的逻辑允许组件响应事件。
<AttachingType>.on<Signal> //<Signal>是信号的名称,首字母必须大写 //我们在处理程序中编写想要实现的效果 on<Property>Changed //属性改变信号处理程序的用法 //<Property>是属性的名称,首字母大写 //都是放在当前元素的内部
信号处理程序
要在为特定对象发出特定信号时接收通知,对象定义应声明一个名为
on<Signal>
的信号处理程序,其中<Signal>
是信号的名称,首字母大写。信号处理程序应包含调用信号处理程序时要执行的 JavaScript 代码。。例如,Qt Quick Controls 模块中的 Button 类型有一个 clicked 信号,每当单击按钮时都会发出该信号。 在这种情况下,用于接收此信号的信号处理程序应该是 onClicked。
在下面的示例中,每当单击按钮时,都会调用 onClicked 处理程序,将随机颜色应用于父 Rectangle:
import QtQuick import QtQuick.Controls Rectangle { id: rect width: 250; height: 250 Button { anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter text: "Change color!" onClicked: { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } }
属性更改信号处理程序
当 QML 属性的值发生变化时,会自动发出信号。 这种类型的信号是属性更改信号,这些信号的信号处理程序以 onChanged 的形式编写,其中 是属性的名称,第一个字母大写。
例如,MouseArea 类型有一个pressed 属性。 要在此属性更改时接收通知,下例为一个名为 onPressedChanged 的信号处理程序:
import QtQuick Rectangle { id: rect width: 100; height: 100 TapHandler { //点击屏幕时,修改了pressed属性,触发onPressedChanged onPressedChanged: console.log("taphandler pressed?", pressed) } }
信号参数
信号可能有参数。 要访问这些,您应该为处理程序分配一个函数。 箭头函数和匿名函数都可以工作。
示例
// Status.qml import QtQuick //注意:函数中形式参数的名称不必与信号中的名称相匹配。 Item { id: myitem signal errorOccurred(message: string, line: int, column: int) }
Status { onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`) //不需要参数时 onErrorOccurred: function (message) { console.log(message) } }
关联信号(Connections)
在某些情况下,可能希望访问发出该信号的对象之外的信号。为此,该QtQuick模块提供用于连接任意对象信号的Connections类型。可以接收来自它的指定的任何信号的目标。
使用场景:
- 将多个对象链接到同一个信号上
- 在发出信号的作用域之外来建立连接
- 发射信号的对象没有在QML中定义
例如,前面示例中的 onClicked 处理程序可能已被根 Rectangle 接收,方法是将 onClicked 处理程序放置在其目标设置为按钮的 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 { //关联button的clicked信号 target: button function onClicked() { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } }
附加信号处理
对象本身或者其基类没有的属性和信号,需要通过外部(附加类型)提供,从附加类型接收一个信号并进行处理
import QtQuick 2.14 Rectangle { width: 200; height: 200 color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1) Component.onCompleted: { //Component 附加类型 console.log("The rectangle's color is", color) } }
自定义类型添加信号
可以通过signal关键字将信号添加到自定义QML类型。定义新信号的语法为:
signal <name>[([<type> <parameter name>[, ...]])]
// SquareButton.qml import QtQuick 2.14 Rectangle { id: root signal activated(real xPosition, real yPosition) //定义一个信号 property point mouseXY property int side: 100 width: side; height: side TapHandler { id: handler onTapped: root.activated(mouseXY.x, mouseXY.y) //发送信号 onPressedChanged: mouseXY = handler.point.position } } // myapplication.qml SquareButton { //处理activated信号 onActivated: console.log("Activated at " + xPosition + "," + yPosition) }
信号连接方法/信号
信号对象使用connect()连接方法或另一个信号。当信号连接到方法时,只要发出信号,该方法就会自动调用。这种机制使信号可以通过方法而不是信号处理程序来接收,也可以通过disconnect()来取消连接.
import QtQuick 2.14 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) } }
使用disconnect()断开信号
Rectangle { id: relay //... function removeTelegraphSignal() { relay.messageReceived.disconnect(sendToTelegraph) } }
信号关联信号
import QtQuick 2.14 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) //关联信号 }