(9)Qt中信号与槽重载的解决方案

信号与槽重载的解决方案

一、通过函数指针解决

//信号
void (Me::*funchungury)() = &Me::hungury;
void (Me::*funchungury_QString)(QString) = &Me::hungury;
//槽
void (Me::*funceat)() = &Me::eat;
void (Me::*funceat_QString)(QString) = &Me::eat;

//有参连接
connect(me,funchungury_QString,me,funceat_QString);
//无参连接
connect(me,funchungury,me,funceat);

继续使用自定义信号时使用的父子窗口切换的案例:

/*
    SubWidget.h文件中添加一个openMainWindow(const QString&)重载信号
*/
#ifndef _SUBWIDGET_H_
#define _SUBWIDGET_H_
#include <QWidget>
#include <QPushButton>

class SubWidget : public QWidget
{
	Q_OBJECT
public:
	SubWidget(QWidget* parent = nullptr);
	~SubWidget();
private:
	QPushButton* m_btn;
signals:
	void openMainWindow();						//	自定义信号
	void openMainWindow(const QString&);		//	带参数的自定义信号
};

#endif
/*
    使用emit发送信号
*/
#include "SubWidget.h"

SubWidget::SubWidget(QWidget* parent)
	:QWidget(parent)
{
	resize(400, 400);
	setWindowTitle("子窗口");

	m_btn = new QPushButton("切换到父窗口", this);
	
	//使用emit发送信号
	connect(m_btn, &QPushButton::clicked, this, [=](){
		emit openMainWindow();
		emit openMainWindow(QString("我是重载的信号"));
	});
}

SubWidget::~SubWidget()
{

}
/*
    Widget.h文件中添加重载的槽函数funcSlot(const QString& msg);
*/
#ifndef _WIDGET_H_
#define _WIDGET_H_

#include <QWidget>
#include <QPushButton>
#include "SubWidget.h"

class SubWidget;
class Widget : public QWidget
{
	Q_OBJECT
public:
	Widget(QWidget* parent = nullptr);
	~Widget();
public slots:
	void funcSlot();						//	不带参数的槽函数
	void funcSlot(const QString& msg);		//	带参数的槽函数
private:
	QPushButton* m_btn = nullptr;
	SubWidget* m_subWidget = nullptr;
};

#endif
#include"Widget.h"

Widget::Widget(QWidget* parent)
	:QWidget(parent)
{
	resize(640, 480);								// 设置父窗口大小
	setWindowTitle("父窗口");						// 设置父窗口标题

	m_btn = new QPushButton("切换到子窗口", this);
	m_subWidget = new SubWidget;

	//实现从父窗口切换到子窗口的效果
	connect(m_btn, &QPushButton::clicked,[=]() {
		this->hide();
		m_subWidget->show();
	});

	//实现从子窗口切换到父窗口的效果
	//使用函数指针的方式解决信号重载	槽重载
	void (SubWidget:: * signalFunc)() = &SubWidget::openMainWindow;
	void (SubWidget:: * signalFunc2)(const QString&) = &SubWidget::openMainWindow;

	void (Widget:: * slotFunc)() = &Widget::funcSlot;
	void (Widget:: * slotFunc2)(const QString&) = &Widget::funcSlot;

	connect(m_subWidget, signalFunc, this, slotFunc);			//	无参连接
	//connect(m_subWidget, signalFunc2, this, slotFunc2);			//	带参连接
}

Widget::~Widget()
{

}

//槽函数
void Widget::funcSlot()
{
	this->show();
	m_subWidget->hide();
}
//重载的带参数的槽函数
void Widget::funcSlot(const QString& msg)
{
	this->show();
	m_subWidget->hide();
	setWindowTitle(msg);
}

上面的案例中,有参数的连接会改变父窗口的标题,没有参数的连接不会改变父窗口的标题。

不带参数的连接:

 

带参数的连接:

 

二、通过Qt提供的重载类(QOverload)解决

//有参连接
connect(this,QOverload<QString>::of(&MyButton::hungury),
        this,QOverload<QString>::of(&MyButton::eat));
//无参连接
connect(this,QOverload<>::of(&MyButton::hungury),
        this,QOverload<>::of(&MyButton::eat));

直接使用QOverload类的方式解决父子窗口切换信号与槽重载的问题:

//使用QOverload的方式解决信号重载	槽重载
connect(m_subWidget, QOverload<>::of(&SubWidget::openMainWindow), 
	this, QOverload<>::of(&Widget::funcSlot));							//	无参连接
connect(m_subWidget, QOverload<const QString&>::of(&SubWidget::openMainWindow),
	this, QOverload<const QString&>::of(&Widget::funcSlot));			//	带参连接

三、使用Qt4的方式解决

        这种旧的信号与槽的连接方式在Qt6中是支持的, 但是不推荐使用, 因为这种方式在进行信号槽连接的时候, 信号和槽函数通过宏SIGNALSLOT转换为字符串类型。因为信号和槽函数的转换是通过宏来进行转换的,因此传递到宏函数内部的数据不会被进行检测, 如果使用者传错了数据,编译器也不会报错,但实际上信号槽的连接已经不对了,只有在程序运行起来之后才能发现问题,而且问题不容易被定位。

Me m;
// Qt4处理方式  注意不要把信号与槽的名字写错了,因为是转为字符串写错了不会报错,但是连接会失败
connect(&m, SIGNAL(eat()), &m, SLOT(hungury()));
connect(&m, SIGNAL(eat(QString)), &m, SLOT(hungury(QString)));

// Qt5处理方式
connect(&m, &Me::eat, &m, &Me::hungury);	// error:no matching member function for call to 'connect'

直接使用Qt4的方式解决父子窗口切换信号与槽重载的问题:

//使用Qt4的方式解决信号重载	槽重载
connect(m_subWidget, SIGNAL(openMainWindow()),
	this, SLOT(funcSlot()));
connect(m_subWidget, SIGNAL(openMainWindow(const QString&)),
	this, SLOT(funcSlot(const QString&)));

总结 

  • Qt4的信号槽连接方式使用了宏函数, 宏函数对用户传递的信号槽不会做错误检测, 容易出bug

  • Qt5的信号槽连接方式, 传递的是信号槽函数的地址, 编译器会做错误检测, 减少了bug的产生

  • 当信号槽函数被重载之后, Qt4的信号槽连接方式不受影响,Qt6中需要给被重载的信号或者槽定义函数指针或者使用QOverload

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

石小浪♪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值