【Qt】带参数的信号和槽函数

🏠个人主页:Yui_

🍑操作环境:Qt Creator

🚀所属专栏:Qt

文章目录

  • [1. 带参数的信号和槽](#1. 带参数的信号和槽)
    • [1.2 参数匹配的信号和槽函数](#1.2 参数匹配的信号和槽函数)
    • [1.2 参数不匹配的信号和槽](#1.2 参数不匹配的信号和槽)
      • [1.2.1 槽函数参数数量大于信号函数](#1.2.1 槽函数参数数量大于信号函数)
      • [1.2.2 信号函数参数数量大于槽函数](#1.2.2 信号函数参数数量大于槽函数)
      • [1.2.3 信号函数和槽函数的参数类型不同](#1.2.3 信号函数和槽函数的参数类型不同)
  • 2.知识补充
    • [2.1 Q_OBJECT](#2.1 Q_OBJECT)
    • [2.1 信号槽多对多](#2.1 信号槽多对多)
  • [3. 总结](#3. 总结)

在前面的文章中,我们已经了解了Qt自带的信号和槽函数以及自定义的信号和槽函数,但是这些都是没有带参数的,其实信号和槽函数是可以带有参数的。

1. 带参数的信号和槽

Qt的信号和槽也是支持带有参数的,同时也支持重载。
此处我们要求,信号函数的参数列表要和对应连接的槽函数参数列表一致。
当信号触发时,调用槽函数的时候,信号函数的实参就能被传递到槽函数的形参当中。

1.2 参数匹配的信号和槽函数

下面我回写一个程序,程序的功能是通过两个按钮来传递参数人窗口的标题发生改变。

cpp 复制代码
#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调用");
}

头文件:

cpp 复制代码
#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

当信号函数和槽函数参数匹配时,并不会发生什么,那么现在让我们来看看参数不匹配的情况下是怎么样的吧。

1.2 参数不匹配的信号和槽

参数不匹配的情况可以分为三种:

  1. 槽函数的参数数量大于信号函数的参数数量但参数类型相同
  2. 信号函数的参数数量大于槽函数的参数数量但参数类型相同
  3. 信号函数和槽函数的参数数量相同但参数类型不同
    下面开始逐个讲解

1.2.1 槽函数参数数量大于信号函数

cpp 复制代码
#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调用");
}
cpp 复制代码
#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

可以看到,编译器报错了,这也就说明了槽函数参数数量大于信号函数是不可以的。

1.2.2 信号函数参数数量大于槽函数

cpp 复制代码
#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个参数,确保槽函数的每个之都是有值。

思考下,为什么会这样呢?又为什么不要求参数的个数严格一致呢?

如果我们要求参数的个数完全一致,就意味着信号绑定到槽函数的要求变高了,换言之当下的规则允许信号和槽函数之间的绑定更加的灵活,更多的信号可以绑定到这个槽函数上了。

1.2.3 信号函数和槽函数的参数类型不同

会报错~

带有参数的信号要求信号的参数和槽函数的参数类型是一致的。

2.知识补充

2.1 Q_OBJECT

Qt中如果要让某个类能够使用信号槽,必须要在类最开始的地方,写下Q_OBJECT宏

使用ALT加右键点击

就可以看到里面的内容了,实际上这里还可以再进一步展开,最终会得到一系列很复杂的代码。

2.1 信号槽多对多

所谓的信号槽,终究要解决的问题就是响应用户的操作。

信号槽,其实在GUI开发的各种框架中是一个比较"有特色"的存在。

大部分的GUI开发框架都是一对一的存在

一个事件只能对应一个处理函数,一个处理函数也只能对应到一个事件上。

就比如网页开发中的JS,网页开发中响应用户操作,主要就是挂回调函数。

而Qt专门搞了一个单独的connect来完成信号槽的连接

Qt信号槽的设计,理想很美好,现实很骨感

该机制主要的效果就是:

  1. 解耦合,把触发用户操作的控件和处理对应用户的操作逻辑解耦合。
  2. 多对多的效果:一个信号可以connect到多个槽函数上,一个槽函数,也可以被多个信号connect。
    那么什么是多对多呢?
    以选课为例,一个学生可以选择多门课,一门课可以被多名学生选择这种。
    多对多真的实用吗?
    答案是否定的,在实际的开发过程中,随着大家的经验越来越多,其实在GUI开发的过程中,多对多就是一个伪需求,实际的开发中很少用到,绝大情况下一对一就够用了。
    所以一些新的图形化开发框架,很少有再继续支持这种多对多的了~

3. 总结

本文我们了解了带参数的信号和槽函数,得知了槽函数会接受到来自信号的参数。且这个参数也是有要求的,信号函数的参数个数可以大于槽函数的参数个数,但是类型必须相同。

相关推荐
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00614 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术14 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript