原理:与C++语法一致,信号、槽函数都可以发生重载,使其在名称不变的情况下,传递过程可以携带参数。
示例说明:我们从一个最普通的信号槽工程中,来修改,对信号、槽进行重载,使信号、槽携带参数。
1. 普通信号 - 工程源码
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); void sendSignalSlot(); void dealSignalSlot(); signals: /* * 信号必须有signals关键字来声明 * 信号没有返回值,但可以有参数 * 信号就是函数的声明,只需声明,无需定义 * 使用:emit mySignal(); * 信号可以重载 */ void mySignal(); private: QPushButton btn1; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { btn1.setParent(this); btn1.setText("sendText"); btn1.resize(80,25); btn1.move(100,100); resize(320, 240); setWindowTitle("Hello!"); connect(&btn1, &QPushButton::clicked, this, &Widget::sendSignalSlot); connect(this, &Widget::mySignal, this, &Widget::dealSignalSlot); } void Widget::sendSignalSlot() { emit mySignal(); } void Widget::dealSignalSlot() { btn1.setText("Done!"); } Widget::~Widget() { }
现象:
- 点击 "sendText" 按钮,按钮文字变为 "Done!"。
2. 带参数的信号、信号重载 - 工程源码
- 信号函数可以发生重载。
- 信号携带参数时,接受的槽函数也必须带参。
- connect使用带参信号时,需要使用函数指针。
- 打印调试信息,需要包含头文件:#include <QDebug>
- 输出字符串需要使用 .toUtf8().data(); 进行转换。
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> #include <QDebug> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); void sendSignalSlot(); void dealSignalSlot(); // 信号带参数,槽函数也要带参 void dealSignalSlotPara(int, QString); signals: /* * 信号必须有signals关键字来声明 * 信号没有返回值,但可以有参数 * 信号就是函数的声明,只需声明,无需定义 * 使用:emit mySignal(); * 信号可以重载 */ void mySignal(); void mySignal(int, QString); private: QPushButton btn1; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { btn1.setParent(this); btn1.setText("sendText"); btn1.resize(80,25); btn1.move(100,100); resize(320, 240); setWindowTitle("Hello!"); connect(&btn1, &QPushButton::clicked, this, &Widget::sendSignalSlot); // 普通信号 void (Widget::*funSingle)() = &Widget::mySignal; connect(this, funSingle, this, &Widget::dealSignalSlot); // 带参数信号 void (Widget::*funSinglePara)(int, QString) = &Widget::mySignal; connect(this, funSinglePara, this, &Widget::dealSignalSlotPara); } void Widget::sendSignalSlot() { emit mySignal(); emit mySignal(100, "发送信号"); } void Widget::dealSignalSlot() { btn1.setText("Done!"); } void Widget::dealSignalSlotPara(int a, QString str) { qDebug() << a << "\t"<< str;// 我的系统环境中,不用转换也可以输出,不过会将""也一并输出 qDebug() << a << "\t"<< str.toUtf8().data();// 需要加转换,才是正常显示 } Widget::~Widget() { }
现象:
- 窗口现象与原工程一致,点击 "sendText" 按钮,按钮文字变为 "Done!"。
- 并且会在应用程序输出窗口,打印传递的参数。
3. 带参数的槽函数、槽函数重载 - 工程源码
信号可以重载,同理,槽函数也同样可以重载:
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> #include <QDebug> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); void sendSignalSlot(); void dealSignalSlot(); // 槽函数也可以重载。信号带参数,槽函数也要带参。 void dealSignalSlot(int, QString); signals: /* * 信号必须有signals关键字来声明 * 信号没有返回值,但可以有参数 * 信号就是函数的声明,只需声明,无需定义 * 使用:emit mySignal(); * 信号可以重载 */ void mySignal(); void mySignal(int, QString); private: QPushButton btn1; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { btn1.setParent(this); btn1.setText("sendText"); btn1.resize(80,25); btn1.move(100,100); resize(320, 240); setWindowTitle("Hello!"); connect(&btn1, &QPushButton::clicked, this, &Widget::sendSignalSlot); // 普通信号 槽函数也可以重载 void (Widget::*funSingle)() = &Widget::mySignal; void (Widget::*funDealSignalSlot)() = &Widget::dealSignalSlot; connect(this, funSingle, this, funDealSignalSlot); // 带参数信号 槽函数也可以重载 void (Widget::*funSinglePara)(int, QString) = &Widget::mySignal; void (Widget::*funDealSignalSlotPara)(int, QString) = &Widget::dealSignalSlot; connect(this, funSinglePara, this, funDealSignalSlotPara); } void Widget::sendSignalSlot() { emit mySignal(); emit mySignal(100, "发送信号"); } void Widget::dealSignalSlot() { btn1.setText("Done!"); } void Widget::dealSignalSlot(int a, QString str) { qDebug() << a << "\t"<< str;// 我的系统环境中,不用转换也可以输出,不过会将""也一并输出 qDebug() << a << "\t"<< str.toUtf8().data();// 需要加转换,才是正常显示 } Widget::~Widget() { }
现象:
- 与上面信号重载的现象一致。
4. Qt4的connect简单写法
用Qt4的写法来写connect信号连接:
(!!!不建议使用,看似写法简单,出了问题很麻烦。因为SIGNAL、SLOT是将函数名称,转换为字符串格式,并且不进行错误检查。一旦写错在编译阶段无任何报错,运行到故障点时才报错,不容易找到错误位置。而且必须用 public slots关键字修饰槽函数。此方法仅做了解,不推荐使用!!!)
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> #include <QDebug> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); public slots: void sendSignalSlot(); void dealSignalSlot(); // 信号带参数,槽函数也要带参 void dealSignalSlotPara(int, QString); signals: /* * 信号必须有signals关键字来声明 * 信号没有返回值,但可以有参数 * 信号就是函数的声明,只需声明,无需定义 * 使用:emit mySignal(); * 信号可以重载 */ void mySignal(); void mySignal(int, QString); private: QPushButton btn1; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { btn1.setParent(this); btn1.setText("sendText"); btn1.resize(80,25); btn1.move(100,100); resize(320, 240); setWindowTitle("Hello!"); connect(&btn1, &QPushButton::clicked, this, &Widget::sendSignalSlot); // // 普通信号 // void (Widget::*funSingle)() = &Widget::mySignal; // connect(this, funSingle, this, &Widget::dealSignalSlot); // // 带参数信号 // void (Widget::*funSinglePara)(int, QString) = &Widget::mySignal; // connect(this, funSinglePara, this, &Widget::dealSignalSlotPara); // Qt4信号连接(不建议用,出了错麻烦,而且必须用 public slots关键字修饰槽函数) // Qt4槽函数必须有public slots关键字来修饰 // 功能等同于上面的用法,不过写错没有错误提示,只有运行时才有调试输出 connect(this, SIGNAL(mySignal()), this, SLOT(dealSignalSlot())); connect(this, SIGNAL(mySignal(int,QString)), this, SLOT(dealSignalSlotPara(int,QString))); } void Widget::sendSignalSlot() { emit mySignal(); emit mySignal(100, "发送信号"); } void Widget::dealSignalSlot() { btn1.setText("Done!"); } void Widget::dealSignalSlotPara(int a, QString str) { qDebug() << a << "\t"<< str;// 我的系统环境中,不用转换也可以输出,不过会将""也一并输出 qDebug() << a << "\t"<< str.toUtf8().data();// 需要加转换,才是正常显示 } Widget::~Widget() { }
现象:
- 与上面信号重载的现象一致。