在前面的文章中,我们已经了解了Qt自带的信号和槽函数以及自定义的信号和槽函数,但是这些都是没有带参数的,其实信号和槽函数是可以带有参数的。
Qt的信号和槽也是支持带有参数的,同时也支持重载。 此处我们要求,信号函数的参数列表要和对应连接的槽函数参数列表一致。 当信号触发时,调用槽函数的时候,信号函数的实参就能被传递到槽函数的形参当中。
下面我回写一个程序,程序的功能是通过两个按钮来传递参数人窗口的标题发生改变。
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(this,&Widget::mySignal,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle(QString s)
{
this->setWindowTitle(s);
}
void Widget::on_pushButton_clicked()
{
emit mySignal("被按钮1调用");
}
void Widget::on_pushButton_2_clicked()
{
emit mySignal("被按钮2调用");
}
头文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QString>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
signals:
void mySignal(QString s);
public slots:
void handle(QString s);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
当信号函数和槽函数参数匹配时,并不会发生什么,那么现在让我们来看看参数不匹配的情况下是怎么样的吧。
参数不匹配的情况可以分为三种:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(this,&Widget::mySignal,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle(QString s1,QString s2)
{
this->setWindowTitle(s1);
}
void Widget::on_pushButton_clicked()
{
emit mySignal("被按钮1调用");
}
void Widget::on_pushButton_2_clicked()
{
emit mySignal("被按钮2调用");
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QString>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
signals:
void mySignal(QString s1);
public slots:
void handle(QString s1,QString s2);
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
可以看到,编译器报错了,这也就说明了槽函数参数数量大于信号函数是不可以的。
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(this,&Widget::mySignal,this,&Widget::handle);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle(QString s)
{
this->setWindowTitle(s);
}
void Widget::on_pushButton_clicked()
{
emit mySignal("被按钮1调用","");
}
void Widget::on_pushButton_2_clicked()
{
emit mySignal("被按钮2调用","");
}
可以正常运行,也就表明信号函数的参数个数超过槽函数的参数个数参数个数是可以正常使用的,但是反过来就是不行,槽函数的参数个数大于信号函数的参数个数,无法编译通过。 个数的不一致,槽函数就会按照参数的顺序拿到信号的前N个参数,确保槽函数的每个之都是有值。 思考下,为什么会这样呢?又为什么不要求参数的个数严格一致呢? 如果我们要求参数的个数完全一致,就意味着信号绑定到槽函数的要求变高了,换言之当下的规则允许信号和槽函数之间的绑定更加的灵活,更多的信号可以绑定到这个槽函数上了。
会报错~ 带有参数的信号要求信号的参数和槽函数的参数类型是一致的。
Qt中如果要让某个类能够使用信号槽,必须要在类最开始的地方,写下Q_OBJECT宏 使用ALT加右键点击
就可以看到里面的内容了,实际上这里还可以再进一步展开,最终会得到一系列很复杂的代码。
所谓的信号槽,终究要解决的问题就是响应用户的操作。 信号槽,其实在GUI开发的各种框架中是一个比较"有特色"的存在。 大部分的GUI开发框架都是一对一的存在 一个事件只能对应一个处理函数,一个处理函数也只能对应到一个事件上。 就比如网页开发中的JS,网页开发中响应用户操作,主要就是挂回调函数。 而Qt专门搞了一个单独的connect来完成信号槽的连接 Qt信号槽的设计,理想很美好,现实很骨感 该机制主要的效果就是:
本文我们了解了带参数的信号和槽函数,得知了槽函数会接受到来自信号的参数。且这个参数也是有要求的,信号函数的参数个数可以大于槽函数的参数个数,但是类型必须相同。