【QML】qml信号和事件处理机制总结

一、开篇

QtQuick有一个信号处理机制,其中信号是事件,信号处理程序能够响应信号。当发出信号时,QtQuick的信号处理机制会调用相应的信号处理程序。在实际QtQuick使用中,则可以在处理程序中放置相应逻辑(例如脚本或其他操作),从而能使组件响应事件。

二、用信号处理程序接收信号

要在为特定对象发出特定信号时接收通知,对象定义应该声明一个名为on< Signal >的信号处理程序,其中< Signal >是信号的名称(注意:首字母必须大写)。信号处理程序应该包含在调用信号处理程序时要执行的JavaScript代码。

三、属性改变信号处理程序

当QML属性的值发生变化时,将自动发出信号。这种类型的信号是属性更改信号,这些信号的信号处理程序以on< Property >Changed的形式编写,其中< Property >是属性的名称,第一个字母必须大写。

四、信号参数

在有些使用场景中,信号可能会带有参数。要访问这些参数,应该给处理程序分配一个函数。

4-1、信号定义

在QML中定义一个信号,格式如下:

signal <name>[([<type> <parameter name>[, ...]])]

在Qt C++中,我们使用emit关键字发出信号;在QML中,发出信号是通过将信号作为方法调用来实现的。

注意:在同一类型块中声明两个具有相同名称的信号或方法是错误的。但是,新信号可能会在该类型上重用现有信号的名称。

如下代码,是定义一个信号的示例

//ReturnBtn.qml 文件

//此处定义一个msgChange信号,该信号带有一个sting类型的参数name,还有一个int类型的参数age
signal msgChange(name:string,age:int)
MouseArea {
    anchors.fill: returnIcon_128

    onClicked: {
      //当点击MouseArea对象类型时,调用msgChange函数,并传入”iriczhao“和999两个参数
        msgChange("iriczhao",999)
    }
    onPressed: {
        glow.visible = true
        glow.color = "lightskyblue"
    }
    onReleased:{
        glow.visible = false
    }
}

4-2、定义信号处理函数接收信号参数

//test.qml文件

Window {
    id: window
    width: 640
    height: 480
    visible: true
    color: "#4c79ef"
    title: qsTr("Hello World")

    ReturnBtn {
        id: returnBtn
        x: 245
        y: 204
        width: 100
        height: 47
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter
	      //此处在msgChange信号处理函数中,使用function()来接收msgChange信号带入的两个参数
        onMsgChange: function(name,age){console.log("recv " + name + " " + age)}
    }
}

1、函数中形式参数的名称不必与信号中的名称相匹配。

2、如果信号处理程序不需要处理所有的参数,可以省略后面的参数。例如:只想在onMsgChange信号处理函数中接收name参数,不接受age参数,可以这样写:

onMsgChange: function(name){console.log("recv "  + " " + name)}

3、对于function()中不需要的参数,可以使用下划线(_)来进行参数占位,从而告诉qml引擎忽略掉该参数。例如,如果不想在onMsgChange信号处理函数中接收name参数,可以这样写:

onMsgChange: function(_,age){console.log("recv "  + " " + age)}

五、使用Connections类型创建信号连接

从上文我们已经知道,当在QML中连接信号时,通常是创建一个on<Signal>的处理程序,当接收到信号的时候这个信号处理函数会被执行。

然而,在某些情况下使用该种方法连接信号和处理函数是不可能的,例如下列三种情况:

(1)需要对同一个信号进行多个连接。

(2)在信号发送器范围之外创建连接。

(3)连接到QML中未定义的目标。

这时候,我们则可以使用Connections类型来连接信号和信号处理函数。例如下列代码:

MouseArea {
    id: area
}

上述代码定义了一个鼠标点击区域,id为area,我们可以使用Connections关联该类型对象的clicked信号:

Connections {
    target: area
    function onClicked(mouse) { foo(mouse) }
}

六、连接信号处理函数

附加的信号处理程序从附加类型接收信号,而不是从声明处理程序的对象接收信号。

例如,Component.onCompleted是一个附加的信号处理程序。它通常用于在创建过程完成时执行一些JavaScript代码。例如下面代码:

import QtQuick 2.0
import QtQuick.Window 2.15
import "Components"

Window {
    id: window
    width: 640
    height: 480
    visible: true
    color: "#4c79ef"
    title: qsTr("Hello World")

    ReturnBtn {
        id: returnBtn
        x: 245
        y: 204
        width: 100
        height: 47
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter

        onMsgChange: function(name){console.log("recv "  + " " + name)}
		
		     //附加的信号处理函数
         Component.onCompleted: {
             console.log("ReturnBtn")
         }
    }
	  //附加的信号处理函数
    Component.onCompleted: {
        console.log("Window")
    }
}

这里将打印出:

qml: Window

qml: ReturnBtn

(注,这里怎么先打印出Window,然后再打印出ReturnBtn呢,这一点与qml的对象树相关)

七、使用connect将信号连接到方法和信号

注意:本文中connectConnections的区别:connect是对象的一个方法,Connections是一个QML类型。

7-1、将信号连接到方法

信号对象有一个connect()方法用来将信号连接到一个方法或信号。当一个信号连接到一个方法时,只要发出信号,该方法就会被自动调用。这种机制使信号可以由方法而不是信号处理程序接收。

那么,这里来重新修改一下ReturnBtn.qml 文件。如下代码:

Window {
    id: window
    width: 640
    height: 480
    visible: true
    color: "#4c79ef"
    title: qsTr("Hello World")

    ReturnBtn {
        id: returnBtn
        x: 245
        y: 204
        width: 100
        height: 47
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter
    }

    Component.onCompleted: {
        //在该组件加载完成信号处理函数中创建:returnBtn对象的msgChange信号与masChangeHandler JavaScript的函数连接。
        returnBtn.msgChange.connect(msgChangeHandler)
    }
	
	  //定义msgChangeHandler函数
    function msgChangeHandler(message,value)
    {
        console.log("recv param :" + message +" " + value);
    }
}

在许多情况下,通过信号处理程序接收信号就足够了,而不必使用connect()函数。但是,使用connect方法允许多个方法接收信号,如前面所示,这对于信号处理程序是不可能的,因为信号处理程序命名必须唯一。

此外,connect方法在将信号连接到动态创建的对象时也很有用。

注意:可以使用disconnect()函数断开信号与方法的连接。如下代码:

function removeMsgChangeSignal(){
    returnBtn.msgChange.disconnect(msgChangeHandler)
}

经实践:发现如果一个信号同时关联信号处理函数和使用connect()函数关联的方法时,会有问题,所以在实际使用中不允许这种操作。

7-2、将信号连接到信号

在QML中,也可以将信号连接到其他信号,可以使用connect()方法形成不同的信号链。此处依然修改ReturnBtn.qml文件,如下代码:

Window {
    id: window
    width: 640
    height: 480
    visible: true
    color: "#4c79ef"
    title: qsTr("Hello World")
    
    //定义returnBtnClicked信号
    signal returnBtnClicked()

    ReturnBtn {
        id: returnBtn
        x: 245
        y: 204
        width: 100
        height: 47
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter
    }

    Component.onCompleted: {
        returnBtn.msgChange.connect(returnBtnClicked)
    }

    onReturnBtnClicked:
    {
        console.log("this is Window signal : returnBtnClicked handler")
    }
}

这样在点击ReturnBtn按钮后,会打印:

this is Window signal : returnBtnClicked handler

八、总结

本文描述了QML开发中,几种信号和信号处理的方法。在Qt提供的QML类型中,许多类型都有自己的信号。信号处理程序有着一个特定的命名规范:on<Signal>。如果需要一个信号创建多个连接,则可以使用Connections类型实现。也可以使用对象类型的connect()方法实现一个信号触发另一个信号,也可以将信号连接到方法。

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
QML中,信号和槽函数是一种用于实现对象间通信的机制,类似于Qt中的信号和槽。信号是来自QML对象的通知,而槽函数则是由信号触发的表达式或函数。在QML中,可以使用signal关键字定义有参或无参的信号。发送信号时,可以使用emit关键字加上信号名和参数进行发送。 为了让信号和槽函数连接起来,需要使用connect函数进行连接。在Qt/C中,连接信号和槽函数需要保持参数顺序和类型一致。而在QML中,连接信号和槽函数更加方便,可以直接在信号和槽之间使用Connections组件进行连接。 例如,在一个QML的Button组件中,可以定义一个信号testSig,然后在按钮点击事件中使用emit关键字发送信号。接着可以使用Connections组件来绑定信号和槽函数,通过onTestSig函数来接收信号。槽函数可以在函数体内进行任意的处理,例如打印参数值。 总结来说,QML中的信号和槽函数机制Qt中类似,可以用于实现对象间的通信和事件处理。通过定义信号、发送信号和连接信号与槽函数,可以实现灵活的交互和逻辑处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【QML事件处理信号与槽](https://blog.csdn.net/m0_60259116/article/details/129265884)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Qml信号的发送与接收信号槽函数的使用](https://blog.csdn.net/Shado_walker/article/details/51243408)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [QML学习笔记【05】:QML信号与槽](https://blog.csdn.net/m0_37845735/article/details/128511282)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

iriczhao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值