QtQuick-QML类型系统-对象特性(信号和信号处理器)

33 篇文章 0 订阅

概念

信号是发生事件(如属性更改、动画状态变化、图片下载完成等)的对象发射的通知。

特定的信号发射后,可以通过相应的信号处理器获得通知。信号处理器的声明语法为:

on<Signal>

其中<Signal>是信号的名字,首字母需要大写。
信号处理器必须在发射信号的对象的定义中进行声明,其中包含调用时要执行的JavaScript代码块。

例如,QtQuick模块中的MouseArea类型就有一个clicked信号。对应的信号处理器为onClciked

import QtQuick

Rectangle{
	id: rect
	width: 400; height:300
	MouseArea{
		anchors.fill: parent
		onClicked:{
			rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
		}
	}
}

1. 声明信号

信号可以在C++中使用Q_SIGNAL宏声明,也可以在QML文档中直接声明。
语法:

signal <signalName>[([<parameterName> : <parameterType>[,...]])]

同一作用域不能有两个同名的信号或方法。但是新的信号可以重用已有信号的名字,这意味着原来的信号会被新的信号隐藏,变得不可访问。

声明信号的例子:

import QtQuick

Item{
	signal clicked
	signal hovered()
	signal actionPerformed(action: string, actionResult: var)
}

没有参数可以省略小括号。有参数必须声明。

还可以用另一种语法来声明:

signal actionCanceled(string action)

2. 属性改变信号

除了自定义的信号,QML类型还提供了一种内建的属性值改变信号。

声明一个自定义的属性,则会隐式地为该属性创建一个值改变信号以及一个相应的信号处理器on<PropertyName>Changed。其中<PropertyName>是自定义属性的名字,首字母大写。

3. 信号处理器

信号处理器是一类特殊的方法特性。

当对应的信号发射时,信号处理器会被QML引擎自动调用。

例子:

//SquareButton.qml
Rectangle {
    id: root

    property int side: 100

    signal activated(real xPosition, real yPosition)
    signal deactivated()

    width: side
    height: side
    color: "red"

    MouseArea {
        anchors.fill: parent
        onReleased: root.deactivated()
        onPressed: (mouse) => {
            return root.activated(mouse.x, mouse.y);
        }
    }
    
}

这些信号可以被SquareButton.qml和同目录的其他QML文件接收,例如:

//main.qml
import QtQuick

Rectangle {
    width: 400
    height: 300

    SquareButton {
        anchors.fill: parent
        onDeactivated: console.log("Deactivated")
        onActivated: (xPosition, yPosition) => {
            return console.log("Activated at " + xPosition + "," + yPosition);
        }
    }

}

在信号处理器中可以通过分配一个函数来访问信号中的参数。可以用例子中的箭头函数,也可以用匿名函数。例如:

onActivated: function(xpos, ypos) {console.log(xPos + "," + yPos)}

其中信号处理器的形参名称不必与信号的参数名称匹配。

可以值处理前面的参数,而略掉其后的参数,例如:

onActivated: (xPos) => console.log("xPosition:" + xPos)

4. Connections类型

除了上面的最基本用法,有时可能需要在发射信号的对象外部使用这个信号。

Qt Quick模块提供了Connections类型,用于连接外部对象的信号。Connections对象可以接收制定目标(target)的任意信号。

例如,下面的代码通过Connections对象,在MouseArea外部处理了MouseArea发出的clicked信号:

Rectangle {
    id: rect

    width: 400
    height: 300

    MouseArea {
        id: mouseArea

        anchors.fill: parent
    }

    Connections {
        function onClicked() {
            rect.color = "red";
        }

        target: mouseArea
    }

}

这段代码中,Connectionstarget属性是mouseArea,因而这个Connections对象可以接收来自mouseArea的任意信号。这里只关心clicked信号,所有只添加了onClicked信号处理器。

通常,使用信号处理器已经能够满足大多数应用。

但是,有时需要把一个信号与一个或多个方法或信号关联起来,这种语法就无能为力了。

QML的信号对象提供了connect()函数,支持将一个信号与一个方法或者另外的信号连接起来,这与Qt/C++类似。

例子,将messageReceived信号与3个方法连接:

import QtQuick

Rectangle {
    id: relay

    signal messageReceived(string person, string notice)

    function sendToPost(person: string, notice: string) {
        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);
    }

    Component.onCompleted: {
        relay.messageReceived.connect(sendToPost);
        relay.messageReceived.connect(sendeToTelegraph);
        relay.messageReceived.connect(sendToEmail);
        relay.messageReceived("Tom", "Happy Birthday");
    }
}

即便这种需求很少,但是也会存在。
更常见的需求是将虚拟号与动态创建的对象关联起来,此时就不得不使用connect()函数进行连接。

如果需要接触连接,可以调用信号对象的disconnect()函数。

不仅如此,使用connect()函数还可以构成一个信号链。
例如:

import QtQuick

Rectangle {
    id: forwarder

    signal send()

    width: 400
    height: 300
    onSend: console.log("Send clicked")
    Component.onCompleted: {
        mouseArea.clicked.connect(send);
    }

    MouseArea {
        id: mouseArea

        anchors.fill: parent
        onClicked: console.log("MouseArea clicked")
    }

}

MouseArea发出clicked信号时,自定义的send信号也会被自动发射。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

barbyQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值