QT笔记——信号转发器之QSignalMapper

news2024/11/15 17:56:55

QSignalMapper类可以看成是信号的翻译和转发器。
它可以把一个无参的信号翻译成带以下4种参数的信号再转发:int、QString、 QObject
以及QWidget

应用场景一般是:有一些信号,发送的参数都是一样的情况下,常用的方法是给每一个信号都连接一个槽函数。但这样做,会让代码多一些不必要的复杂,这种情况下,你就可以使用QSignalMapper
在这里插入图片描述

下面是 3 个按钮连接 到 对应的 映射数据
setMapping 设置 发射对象 接受的数据

意思:m_signalMapper 作为一个中转站 点击按钮 给到 m_signalMapper,用map来翻译 这个 数据,然后m_signalMapper 发射mapped信号 将刚才翻译的数据发送给 this,这个this 就是我们最终的 接受者
目的:这时候我们就将3个按钮的点击信号 都交给 m_signalMapper 去处理,它发射一个信号mapped 就 节省了 3个按钮 都需要写connect 非必要操作,因为他们的 目的 都是 去 触发showName 这个槽函数,现在我们只需要一个 conenct 就可以解决

	m_signalMapper = new QSignalMapper(this);

	m_signalMapper->setMapping(ui.btn1, "Button 1 clicked");
	m_signalMapper->setMapping(ui.btn2, "Button 2 clicked");
	m_signalMapper->setMapping(ui.btn3, "Button 3 clicked");

	connect(ui.btn1, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
	connect(ui.btn2, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
	connect(ui.btn3, SIGNAL(clicked()), m_signalMapper, SLOT(map()));

	connect(m_signalMapper, SIGNAL(mapped(const QString&)), this, SLOT(showName(const QString&)));
	connect(m_signalMapper, SIGNAL(mapped(QString)), this, SLOT(showStrName(QString)));

结果:

在这里插入图片描述
来看一下如果参数为 QObejct是怎么回事

这里有一个StudentInfo 类型 是继承于QObject的,然后分别设置了它的参数,此时我们就知道,点击按钮,然后将 这个学生的信息 交给我们的 m_signalMapper,然后它 在转发给我们的 showStudentInfo 函数,这里函数展示了我们学生的信息情况,也同样不需要写 3个 connect 来操作

	m_s1.SetName("lion");
	m_s1.SetAge(20);

	StudentInfo* s2 = new StudentInfo("cxq", 18);
	StudentInfo* s3 = new StudentInfo("lion_cxq", 22);

	m_signalMapper->setMapping(ui.btn1, &m_s1);
	m_signalMapper->setMapping(ui.btn2, s2);
	m_signalMapper->setMapping(ui.btn3, s3);

	connect(ui.btn1, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));
	connect(ui.btn2, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));
	connect(ui.btn3, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));

	connect(m_signalMapper, QOverload<QObject*>::of(&QSignalMapper::mapped), this, &QSignalMapperTest::showStudentInfo);

关键的一点是:
我们可以在槽函数中 将QObject 转化为我们 自定义的指针

void QSignalMapperTest::showStudentInfo(QObject* object)
{
	StudentInfo* s = qobject_cast<StudentInfo*>(object);
	if (s)
	{
		qDebug() << s->GetAge() << s->GetName();
	}
}

还有一个就是我们遇到同名的 槽函数时,我们必须要同时两边重载,使用一个即可,否则会报错

	//第一个
	connect(m_signalMapper, QOverload<const QString&>::of(&QSignalMapper::mapped), this, QOverload<const QString&>::of(&QSignalMapperTest::showName));
	//第二个
	connect(m_signalMapper, static_cast<void (QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped), this, static_cast<void (QSignalMapperTest::*)(const QString&)>
(&QSignalMapperTest::showName));

结果:
在这里插入图片描述
完整代码:
ui图
在这里插入图片描述

.h

#pragma once

#include <QtWidgets/QWidget>
#include "ui_QSignalMapperTest.h"
#include <QSignalMapper>
#include <QDebug>
#include <QVariant>

#define QT5

typedef struct Student
{
	QString name;
	int age;
}Student;
Q_DECLARE_METATYPE(Student)

class StudentInfo :public QObject
{
	Q_OBJECT
public:
	StudentInfo(QObject* parent = nullptr);
	StudentInfo(QString name, int age, QObject* parent = nullptr);

	void SetName(const QString&);
	QString GetName() const;

	void SetAge(const int&);
	int GetAge() const;

private:
	QString m_name;
	int m_age;
};

class QSignalMapperTest : public QWidget
{
    Q_OBJECT

public:
    QSignalMapperTest(QWidget *parent = Q_NULLPTR);

public Q_SLOTS:
	void showName(const QString&);
	void showName(QString, int);
	void showStrName(QString);
	void showStudentInfo(QObject* object);


private:
    Ui::QSignalMapperTestClass ui;

	StudentInfo m_s1;
	QSignalMapper* m_signalMapper;
};

.cpp

#include "QSignalMapperTest.h"

QSignalMapperTest::QSignalMapperTest(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

	m_signalMapper = new QSignalMapper(this);

#if 1
	#ifdef QT5
	m_s1.SetName("lion");
	m_s1.SetAge(20);

	StudentInfo* s2 = new StudentInfo("cxq", 18);
	StudentInfo* s3 = new StudentInfo("lion_cxq", 22);

	m_signalMapper->setMapping(ui.btn1, &m_s1);
	m_signalMapper->setMapping(ui.btn2, s2);
	m_signalMapper->setMapping(ui.btn3, s3);

	connect(ui.btn1, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));
	connect(ui.btn2, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));
	connect(ui.btn3, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));

	connect(m_signalMapper, QOverload<QObject*>::of(&QSignalMapper::mapped), this, &QSignalMapperTest::showStudentInfo);
	#else
	StudentInfo* s = new StudentInfo("cxq", 18);

	m_signalMapper->setMapping(ui.btn1, s);
	m_signalMapper->setMapping(ui.btn2, s);
	m_signalMapper->setMapping(ui.btn3, s);

	connect(ui.btn1, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
	connect(ui.btn2, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
	connect(ui.btn3, SIGNAL(clicked()), m_signalMapper, SLOT(map()));

	connect(m_signalMapper, SIGNAL(mapped(QObject*)), this, SLOT(showStudentInfo(QObject*)));
	#endif
#endif

#if 0
	#ifdef QT5
	m_signalMapper->setMapping(ui.btn1, "Button 1 clicked");
	m_signalMapper->setMapping(ui.btn2, "Button 2 clicked");
	m_signalMapper->setMapping(ui.btn3, "Button 3 clicked");

	connect(ui.btn1, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));
	connect(ui.btn2, &QPushButton::clicked, m_signalMapper, QOverload<>::of(&QSignalMapper::map));
	connect(ui.btn3, &QPushButton::clicked, m_signalMapper, static_cast<void(QSignalMapper::*)()>(&QSignalMapper::map));

	//使用这个报错  必须使用下面第一种或者第二种  因为 槽函数也是重载的
	//connect(m_signalMapper, QOverload<const QString&>::of(&QSignalMapper::mapped), this, &QSignalMapperTest::showName);
	//第一个
	//connect(m_signalMapper, QOverload<const QString&>::of(&QSignalMapper::mapped), this, QOverload<const QString&>::of(&QSignalMapperTest::showName));
	//第二个
	connect(m_signalMapper, static_cast<void (QSignalMapper::*)(const QString&)>(&QSignalMapper::mapped), this, static_cast<void (QSignalMapperTest::*)(const QString&)>(&QSignalMapperTest::showName));
	#else
	m_signalMapper->setMapping(ui.btn1, "Button 1 clicked");
	m_signalMapper->setMapping(ui.btn2, "Button 2 clicked");
	m_signalMapper->setMapping(ui.btn3, "Button 3 clicked");

	connect(ui.btn1, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
	connect(ui.btn2, SIGNAL(clicked()), m_signalMapper, SLOT(map()));
	connect(ui.btn3, SIGNAL(clicked()), m_signalMapper, SLOT(map()));

	//可以
	connect(m_signalMapper, SIGNAL(mapped(const QString&)), this, SLOT(showName(const QString&)));
	connect(m_signalMapper, SIGNAL(mapped(QString)), this, SLOT(showStrName(QString)));
	//不可以  多个参数不可以
	//connect(m_signalMapper, SIGNAL(mapped(QString,int)), this, SLOT(showName(QString,int)));
	#endif
#endif
}

void QSignalMapperTest::showName(const QString& str)
{
	qDebug() << str;
}

void QSignalMapperTest::showName(QString name, int age)
{
	qDebug() << QStringLiteral("姓名:");
}

void QSignalMapperTest::showStrName(QString str)
{
	qDebug() << str;
}

void QSignalMapperTest::showStudentInfo(QObject* object)
{
	StudentInfo* s = qobject_cast<StudentInfo*>(object);
	if (s)
	{
		qDebug() << s->GetAge() << s->GetName();
	}
}

StudentInfo::StudentInfo(QObject* parent)
{

}

StudentInfo::StudentInfo(QString name, int age, QObject* parent )
{
	m_name = name;
	m_age = age;
}

void StudentInfo::SetName(const QString& name )
{
	m_name = name;
}

QString StudentInfo::GetName() const
{
	return m_name;
}

void StudentInfo::SetAge(const int& age)
{
	m_age = age;
}

int StudentInfo::GetAge() const
{
	return m_age;
}

参考博客:
QSignalMapper介绍
QSignalMapper使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/441220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mapreduce基础: 手写wordcount案例

文章目录 一、源代码二、运行截图 一、源代码 WordCountMapper类 package org.example.wordcount;import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper;impo…

[架构之路-169]-《软考-系统分析师》-4-据通信与计算机网络-0-Ad hoc网络(分组无线网络)

目录 什么是Ad hoc网络 adhoc无线网络的历史 ad hoc特点 独立性 结构 通信带宽 主机能源 分布式特性 生存周期 物理安全 adhoc无线网络的结构 adhoc无线网络的应用 什么是Ad hoc网络 Ad hoc是一种多跳的、无中心的、自组织无线网络&#xff0c;又称为多跳网&#xff08;M…

天龙八部手游服务端架设搭建教程

天龙八部手游服务端架设搭建教程 大家好&#xff0c;我是艾西。最近更新游戏搭建教程比较少也被不少小伙伴催更&#xff0c;今天我和大家聊聊天龙八部手游服务端架设搭建。 游戏讲述元佑元年&#xff0c;大宋遭受辽国入侵的故事&#xff0c;玩家可扮演峨眉、丐帮、天山、逍遥、…

SQL Server基础 第一章 (新建,分离,附加)

目录 前言 一&#xff0c;新建数据库 二&#xff0c;分离数据库 1&#xff0c;右键数据库&#xff0c;任务&#xff0c;分离 2&#xff0c;右键数据库&#xff0c;任务&#xff0c;分离 三&#xff0c;附加数据库 前言 本文主要详细介绍SQL server2019的简单使用&#xf…

ESP8266 +I2C SH1106 OLED仿数码管时钟

ESP8266 +I2C SH1106 OLED仿数码管时钟 📌相关篇《ESP8266 +I2C SSD1306 OLED仿数码管时钟》🎞🎬显示效果: 🔖本工程基于Arduino IDE框架下开发。🌿采用esp8266:Nodemcu📑配置参数信息: ✨在上面一篇的基础上做了改版,去除掉了原来在SSD1306那版中获取时间的NTP…

微信小程序制作

小程序是一种在移动设备上使用的轻量级应用程序&#xff0c;不需要下载安装&#xff0c;具有体积小、加载快和用户粘性高的优点。对于创业者和企业来说&#xff0c;开发一个小程序可以帮助他们拓宽商业渠道、增强品牌影响力和提升用户体验。那么&#xff0c;要开发一个小程序&a…

【Spring6】| 简述Spring中的八大模式

一&#xff1a;Spring中的八大模式 Spring中的八大模式&#xff0c;有很多我们前面已经讲过了&#xff0c;这里只需要大概有个印象&#xff0c;后期会出一个专门对23种设计模式的详解&#xff01; 1. 简单工厂模式 BeanFactory的getBean()方法&#xff0c;通过唯一标识来获取…

51单片机(8051系列)最小系统图--内部时钟

最小系统电路图&#xff08;无源晶振&#xff09; 电容的作用 C1,C2&#xff1a;协助晶振起振&#xff08;一般称为负载电容&#xff09; 解释&#xff1a; 负载电容的计算公式CL C1*C2 / &#xff08;C1C2&#xff09; CS 其中CS为电路板的寄生电容一般取3~5pF 一般情况下&…

对表中数据进行删改,基础查询

目录 一.DML&#xff1a;对表中的数据进行增删改 二.DQL 一.DML&#xff1a;对表中的数据进行增删改 1.添加:insert 2.修改&#xff1a;update 3.删除&#xff1a;delete 二.DQL 1.基础查询&#xff1a; 2. 排序查询 3.聚合函数 概念&#xff1a;将一列数据作为一个整体&am…

带你彻底理解栈和队列

文章目录 前言一、栈是什么&#xff1f;二、栈的使用1.方法2.代码实现 三.栈的模拟四.队列1.方法2.代码实现3.循环队列4.双端队列 总结&#xff1a; 前言 今天&#xff0c;带你彻底理解栈和队列。 一、栈是什么&#xff1f; 栈英文叫做stack&#xff0c;是一种特殊的线性表。…

ARM busybox 的移植实战1

前言 先逐步构建 “文件夹形式”的根文件系统&#xff0c;然后制作烧录镜像。 (1) rootfs 有 2 种格式&#xff1a;nfs 方式启动的 “文件夹形式” 的 rootfs&#xff0c;和用来烧录的镜像形式的 rootfs。 (2) 我们先从空文件夹开始&#xff0c;逐步向其中添加一些 rootfs 中…

消息队列总结

消息队列 KafkaRocketMQRabbitMQActiveMQZeroMQMQ对比选型结论 消息队列的优点&#xff1a; 实现系统解耦实现异步调用流量削峰 消息队列的缺点&#xff1a; 系统可用性降低提升系统的复杂度数据一致性问题 Kafka Apache Kafka 是一个分布式消息发布订阅系统。它最初是由Li…

通过ObjectMapper和JsonNode 把JSON字符串转换成树结构数据和获取树节点数据

一.简介 今天同事有个需求&#xff0c;要把一个JSON字符串转换成一个树结构的数据并获取节点数据&#xff0c;鉴于自己不想写递归去转换&#xff0c;于是使用ObjectMapper和JsonNode类去实现。 二.依赖 pom文件引入依赖&#xff1a; <dependency><groupId>com.…

leetcode每日一题——美团笔试题【1】

今天分享两道算法题&#xff0c;自己刚开始练习&#xff0c;可能在解法上不是最佳的&#xff0c;但是只提供一些自己的思路&#xff0c;欢迎大家多多指教~ 第一题 实现一个算法&#xff0c;确定一个字符串 s 的所有字符是否全都不同。 示例 1&#xff1a;输入: s "lee…

NUC980驱动595与165扩展输入输出接口

一、电路图 3个165串联组成扩展24路光耦输入检测&#xff0c;一个595扩展8路继电器输出 二、驱动源码 #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/device.h>#include <linux/kernel.h> #in…

【C++ 学习 ①】- C++ 入门知识(上万字详解)

目录 一、历史 1.1 - C 语言的发展历程 1.2 - C 发展历程 二、C 关键字&#xff08;C98&#xff09; 三、命名空间 3.1 - 命名空间的定义 3.2 - 命名空间的使用 四、C 输入&输出 五、缺省参数 5.1 - 缺省参数的概念 5.2 - 缺省参数的分类 六、函数重载 6.1 - …

JavaSE学习进阶day05_03 泛型(进阶)

第五章 泛型&#xff0c;之前基础班学习过泛型&#xff0c;但是学的不深入 需要我们掌握的内容&#xff1a;&#xff08;掌握&#xff09; 1&#xff0c;如何使用一个带有泛型的类 2&#xff0c;如何使用一个带有泛型的方法 代码示例&#xff1a; ArrayList<String> lis…

浏览器插件官方demo学习(五):键盘快捷键、数据缓存、网络请求监听

键盘快捷键 这个demo主要是介绍了&#xff0c;通过自定义键盘快捷键的方式来触发扩展。 必须要在manifest.json文件中添加commands属性组合键&#xff1a;使用组合键时必须包含 Ctrl 或 Alt 细节不介绍&#xff0c;可以自行查看官方文档。这里只看一下常用的东西。 定义组合…

MYSQL第一讲:一个查询语句需要经过多少步?

1.连接器 负责客户端和MYSQL连接时的校验和权限验证 短连接&#xff1a;一段时间就断开然后重连&#xff0c;身份校验和权限验证不是一个轻松的活。所以不推荐 长连接&#xff1a;一般的情况都是长连接&#xff0c;但是长连接如果长时间不断开&#xff0c;会出问题&#xff…

Vulnhub项目:MrRobot

靶机地址&#xff1a;Mr-Robot: 1 ~ VulnHub 渗透过程&#xff1a; 先看描述&#xff0c;有3跟keys在这个靶机中 首先确定靶机ip&#xff0c;对靶机开放的端口进行探测 访问靶机地址&#xff0c;出现了很酷炫的web界面&#xff0c;这个mr.robot,是一个美剧&#xff0c;还是挺…