百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

【QML事件处理】信号与槽

bigegpt 2024-09-16 12:13 7 浏览

信号和槽作为 Qt 的核心机制,在 Qt 编程中有着广泛的应用。同样,QML 也继承了这样的特性 - 信号和信号处理程序 ,只不过叫法上略有不同。

  • 信号:来自 QML 对象的通知。
  • 信号处理程序:由信号触发的表达式(或函数),也被称为 Qt C++ 中的 “槽”。

信号是事件,信号通过信号处理程序来响应。当一个信号被发射时,相应的信号处理程序就会被调用,在处理程序中放置逻辑(例如:脚本或其他操作)以允许组件响应事件。

1、自定义信号槽的声明与使用

可以通过 signal 关键字来添加自定义信号,语法如下:

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

在 QML 中自定义信号signal clickButton(),默认有一个onClickButton的信号处理程序(槽函数)自动与之相关联,信号处理程序必须在发出信号的对象定义中声明。

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.3

Window {
    id: window
    visible: true
    width: 200
    height: 200
    title: qsTr("hello world")

    // 自定义信号
    signal clickButton()

    Text {
        id: testText
        text: qsTr("text")
    }

    // 发送信号
    MouseArea {
        anchors.fill: parent
        onClicked: clickButton()
    }

    // 信号处理函数(格式:on<Signal>)
    onclickButton: testText.text = "OK";
}

点击窗口可以查看到 text 变成 OK 说明成功。

QT开发交流+赀料君羊:714620761

2、页面间使用信号槽传递消息

先看效果:

CountSetPage.qml

Rectangle {
    id: countSetPage
    
	// 1.自定义信号,传递信息
	signal clickBtnOk(string strName, string strDate)    
    
    // 确定按钮
    Button {
        text: qsTr("确定")
        font.pointSize: 20

        anchors.right: parent.right
        anchors.rightMargin: 40
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 12
        onClicked: {
            if(textAreaName.text == "" && textAreaDate.text == "")
                console.log("编辑框必须有输入")

            // 2.发送信号(名称 + 剩余天数)
            countSetPage.clickBtnOk(textAreaName.text, textAreaDate.text)

            // 关闭该页面
            countSetPage.destroy()
        }
    }
}    

CountDownPage.qml

Rectangle {
    id: countDownPage    
    
    // 3.定义接收槽函数
    function recvName2Date(strName, strDate){
        console.log(strName + " " + strDate);
        textName.text = String("距离%1还有").arg(strName)
        textDate.text = strDate
    }
    
    // 设置按钮
    Button {
    width: 32
    height: 32
    text: qsTr("设置")
    anchors.right: parent.right
    anchors.rightMargin: 8
    anchors.verticalCenter: parent.verticalCenter
    onClicked: {
    	var component = Qt.createComponent("CountSetPage.qml");    	
    	if (component.status === Component.Ready) {
    		var object = component.createObject(iotMainPage, {x:100, y:50, 						                 width:400, height:320})
            // 4.使用connect连接信号槽
    		object.clickBtnOk.connect(recvName2Date);
    	}
    }  
}    

3、系统自带的信号处理程序

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

当 QML 属性值发生改变时,将自动发出信号。这种类型的信号是属性改变信号,对应的处理程序为属性改变信号处理程序。

属性改变信号处理程序以on<Property>Changed的形式写入,<Property>是属性的名称,首字母大写。

例如,MouseArea 类型具有pressed属性,要在该属性改变时接收通知,需要编写名onPressedChanged的信号处理程序:

QT开发交流+赀料君羊:714620761

import QtQuick 2.2

Rectangle {
    id: rect
    width: 100
    height: 100

    MouseArea {
        anchors.fill: parent
        onPressedChanged: {
            // 鼠标按下/释放
            console.log("Mouse area is pressed?", pressed)
        }
    }
}

/* 
点击两下后的输出:
qml: Mouse area is pressed? true
qml: Mouse area is pressed? false
qml: Mouse area is pressed? true
qml: Mouse area is pressed? false
*/

尽管 MouseArea 文档中没有记录名为onPressedChanged的信号处理程序,但是因为存在 pressed 属性,所以它也被隐式地提供了。

3.2、使用 Connections 类型

QtQuick 模块提供了 Connections 类型,用于连接到任意对象的信号。Connections 的优点是: 可以在发射信号的对象外部访问该信号。

例如,上述示例中的onClicked处理程序可以由根 Rectangle 接收,只需要将其放置在一个 Connections 对象中,并指定 target 为 mouseArea:

import QtQuick 2.2

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Connections {
        target: mouseArea
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

3.3、附加信号处理器

附加信号处理程序所接收的信号来自附加类型,而非声明处理程序的对象。附加,也称为额外。可以简单理解为:对象本身或其基类没有的属性和信号,需要通过外部(附加类型)提供。

要引用附加属性和处理程序,可以使用以下语法形式:

  • <AttachingType>.<propertyName>
  • <AttachingType>.on<SignalName>

例如,下面的 Item 可以通过附加类型 Keys 来访问其附加属性和附加信号处理程序:

import QtQuick 2.2

Item {
    width: 100; height: 100

    focus: true
    Keys.enabled: true
    Keys.onReturnPressed: console.log("Return key was pressed")  // 按下回车键,打印 log 信息
}

enabled 是 Keys 的一个属性,为其赋值为 true(默认值是 true,这里主要用于说明如何使用附加类型的属性),表明启用键盘处理。由于 Keys 提供了returnPressed信号,所以可以通过onReturnPressed来引用相应的附加信号处理程序。

类似的附加类型还有很多,例如:Component,它有一个onCompleted附加信号处理程序,通常用于在创建完成后执行某些 JavaScript 代码:

import QtQuick 2.2

Rectangle {
    width: 200; height: 200
    color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1)

    Component.onCompleted: {
        console.log("The rectangle's color is", color)
    }
}

onCompleted处理程序没有响应来自 Rectangle 类型的 completed 信号。相反,Component 对象由 QML 引擎自动附加到 Rectangle 对象,当对象完全创建时,引擎发出completed信号,从而触发Component.onCompleted信号处理程序。


4、信号到方法/信号的连接

大部分情况下,通过信号处理程序接收信号就足够了,然而,要将信号连接至多个方法/信号,这对于信号处理程序来说是不可能的(因为信号处理程序的命名必须唯一)。

在 Qt C++ 中,信号与槽的连接方式使用的是QObject::connect()。相应地,在 QML 中,signal 对象也有一个 connect() 方法,用于将信号连接到一个方法或另一信号。当信号连接到方法时,无论信号何时发出,该方法都将被自动调用。有了这种机制,可以通过方法来接收信号,而无需使用信号处理器。

所以呢,相对于信号处理程序来说,connect() 更加灵活,可以将信号连接至多个方法/信号 。

4.1、信号到方法的连接

下面,使用 connect() 方法将 messageReceived 信号连接到两个方法:

import QtQuick 2.2

Rectangle {
    id: relay

    signal messageReceived(string message, string qq)

    Component.onCompleted: {
        relay.messageReceived.connect(sendToLiLei)  // 连接信号和方法
        relay.messageReceived.connect(sendToHanMeimei)  // 连接信号和方法
        relay.messageReceived("Welcome to join us(QML分享与交流)", "26188347")  // 发射信号
    }

    function sendToLiLei(message, qq) {
        console.log("Sending to LiLei: " + message + ", " + qq)
    }
    function sendToHanMeimei(message, qq) {
        console.log("Sending to HanMeimei: " + message + ", " + qq)
    }
}

广播一下,李雷和韩梅梅就可以很快的找到组织了!

有 connect() 方法,必然也会有相应的 disconnect() 方法,用于删除连接的信号:

Rectangle {
    id: relay
    //...

    function removeLiLeiSignal() {
        relay.messageReceived.disconnect(sendToLiLei)
    }
}

用法很简单,和 connect() 相同。

4.2、信号到信号的连接

通过将信号连接到其他信号,connect() 方法可以形成不同的信号链。

QT开发交流+赀料君羊:714620761

import QtQuick 2.2

Rectangle {
    id: forwarder
    width: 100; height: 100

    signal sendToLiLei()  // 自定义信号
    signal sendToHanMeimei()  // 自定义信号
    onSendToLiLei: console.log("Send to LiLei")  // 信号处理程序
    onSendToHanMeimei: console.log("Send to HanMeimei")  // 信号处理程序

    MouseArea {
        id: mousearea
        anchors.fill: parent
        onClicked: console.log("Clicked")
    }

    Component.onCompleted: {
        // 连接信号至两个信号
        mousearea.clicked.connect(sendToLiLei)
        mousearea.clicked.connect(sendToHanMeimei)
    }
}

每当 MouseArea 的 clicked 信号被发射,sendToLiLei、sendToHanMeimei 信号也将自动发射,从而执行对应的信号处理程序。 这时,输出如下:

Clicked
Send to LiLei
Send to HanMeimei

建议: 在 QML 中,信号和信号处理器程序是一个核心机制,一定要熟练掌握。

相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...