QT自定义信号与槽

QT自定义信号与槽

概念:

所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。

槽的本质是类的成员函数,其参数可以是任意类型的。和普通C++成员函数几乎没有区别,它可以是虚函数;也可以被重载;可以是公有的、保护的、私有的、也可以被其他C++成员函数调用。唯一区别的是:槽可以与信号连接在一起,每当和槽连接的信号被发射的时候,就会调用这个槽。

槽能被用来接收信号者,除此之外它们也是普通的成员函数。槽不知道是否有信号与它连接起来,正如对象不知道它发出信号是否会被接收一样。这样的机制确保了可以使用Qt创建一个个完全独立的组件。你可以把你感兴趣的多个信号与一个个槽进行连接,也可以把一个信号与多个槽进行连接。甚至可以直接把一个信号连接到另一个信号(当第一个信号发送出去的时候,第二个信号紧接着被发送)。就这样,信号与插槽建立了强大的组件编程机制。

connect()函数最常用的一般形式:

connect(sender, signal, receiver, slot);

参数设置:

  • sender:发出信号的对象
  • signal:发出信号的对象发出的信号
  • receiver:接收信号的对象
  • slot:接收信号的对象在接收到信号之后所需要调用的函数

信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)。

QT自定义信号与槽_第1张图片

自定义槽
  • 槽可以是任何成员函数、普通全局函数、静态函数
  • 槽函数和信号的参数和返回值要一致
  • 由于信号是没有返回值的, 槽函数也一定没有返回值
    首先在mainwidget.h中添加槽函数:
public slots:
    void ASlot();

之后在mainwidget.cpp文件中定义槽函数:

void MainWidget::ASlot()
{
    btn2->setText("^_^");
}

现在, 我们希望当Button2按下时, Button2显示的文本变成笑脸, 就需要将Button2的信号和我们自定义的槽函数连接:

connect(btn2, &QPushButton::clicked, this, &MainWidget::ASlot);

代码:

mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include 
#include 
#include "subwidget.h"

class mainWidget : public QWidget
{
    Q_OBJECT

private:
    QPushButton btn1;
    QPushButton *btn2;

public slots:
    void Aslots();

public:
    mainWidget(QWidget *parent = 0);
    ~mainWidget();
};

#endif // MAINWIDGET_H

mainwidget.cpp

#include "mainwidget.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    btn1.setParent(this);
    btn1.setText("Close");
    btn1.move(50,50);

    btn2 = new QPushButton(this);
    btn2->setText("btn_ok");
    btn2->move(150,50);

    connect(&btn1, &QPushButton::clicked, this, &MainWidget::close);

    connect(btn2, &QPushButton::clicked, this, &MainWidget::ASlot);

}

void MainWidget::ASlot()
{
    btn2->setText("^_^");
}

MainWidget::~MainWidget()
{

}

QT自定义信号与槽_第2张图片

自定义信号

实现两个独立窗口之间的切换, 点击"Next" 跳到下一个窗口, 点击"Back" 返回到上一个窗口.

  • 信号没有返回值, 但可以有参数
  • 信号只有函数声明, 无需定义
  • 使用emit 发送信号
    首先修改当前窗口标题为"Window1", 并设置窗口大小:
    this->setWindowTitle("Window1");  // this->可以省略
    this->resize(300, 200);  // 长300, 宽200

之后修改Button2的文本"Button2"为"Next"
新建一个窗口
右键工程目录**“SignalAndSlot”** --> Add New:
QT自定义信号与槽_第3张图片
选择 C++ --> C++ Class --> Choose:
QT自定义信号与槽_第4张图片
输入Class name为SubWidget, Base class为QWidget, 点击Next, 点击Finish:
QT自定义信号与槽_第5张图片
之后一个新的窗口类就新建好了:
QT自定义信号与槽_第6张图片

修改新窗口的标题:
在subwidget.cpp中构造函数下, 设置窗口的标题为"Window2", 大小和Windows1一样:

    this->setWindowTitle("Windows2");
    this->resize(300, 200);

在新窗口中加入按键:
首先, 在subwidget.h中添加头文件, 然后声明按钮 b:

private:
    QPushButton b;

在subwidget.cpp中, 对按钮进行编辑:

    b.setParent(this);
    b.setText("Back");
    b.move(150, 50);

实例化SubWidget:
但是, 我们仅仅是写了一个新窗口的类, 还没有实例化, 所以我们在mainwidget.h中先包含subwidget的头文件, 然后实例化一个副窗口subWin对象:

    SubWidget subWin;

建立信号与槽的连接:
接下来, 我们来实现点击"Next"显示Windows2功能, 其实就是b2点击这个信号, 触发副窗口的show(), 并隐藏主窗口.
将mainwidget.h和mainwidget.cpp中所有的mySlot改为nextSlot. (共三处)
我们修改mainwidget.cpp中nextSlot()的定义:

void MainWidget::nextSlot()
{
    //  删除 b2->setText("^_^");
    subWin.show();
    this->hide();
}

connect(b2, &QPushButton::clicked, this, &MainWidget::nextSlot);不变. 保存并运行, 就可以实现切换到Window2窗口了. 但是还没有返回主窗口功能.
信号的创建和发送:
要实现Back功能, 就需要在"Back"按钮按下后, 副窗口发送一个信号, 然后主窗口收到这个信号后, 显示自己, 隐藏副窗口, 逻辑如下:
Back按下的信号 ----> 副窗口发送信号
副窗口的信号 ----> 主窗口show, 副窗口hide
下面看代码怎么写:
在subwidget.h中声明一个自定义的信号, 和用于发送该信号的槽函数:

signals:
    void backSignal();

public slots:
    void sendSignal();

由于信号只需声明, 无需定义, 所以只要在subwidget.cpp定义槽函数来发送信号:

void SubWidget::sendSignal()
{
    emit backSignal();
}

之后在Back按钮按下后, 通过这个槽函数发送返回信号:

connect(&b, &QPushButton::clicked, this, &SubWidget::sendSignal);

在mainwidget中需要再定义一个槽函数来处理back信号:
在mainwidget.h中声明槽函数

    void backSlot();

之后在mainwidget.cpp中定义:

void MainWidget::backSlot()
{
    this->show();
    subWin.hide();
}

之后connect信号与槽, 收到副窗口发送的信号后返回主窗口:

    connect(&subWin, &SubWidget::backSignal, this, &MainWidget::backSlot);

保存后运行, 现在可以在两个界面中切换了.
QT自定义信号与槽_第7张图片
QT自定义信号与槽_第8张图片

自己完成以下代码吧

完整代码:

链接: https://pan.baidu.com/s/1rtXU8e0oUy95mAok1zRDIA 密码: 7tc3
–来自百度网盘超级会员V5的分享

QT自定义信号与槽_第9张图片

你可能感兴趣的:(qt,c++,qt)