【Qt教程】1.6 - Qt5信号与槽、Single Slot emit、自定义信号、自定义槽

信号与槽

1. 说明

概念:信号和槽,是Qt对象间通信的接口。信号Signal、槽Slot,分别对应着事件的发送端和接受端。

语法

connect(  信号的发送者,  发送的具体信号,  信号的接收者,  信号的处理(槽)  );

信号槽的优点:松散耦合。信号发送端 和 接收端 本身是没有关联的,通过 connect连接 将两端耦合在一起。

事件的方法:查看 要操作对象的父类:QPushButton、QWidget,查询帮助手册的 Signals、Slots 事件

 

 

2. 用法示例

示例需求:点击按钮时,可以关闭掉窗口。

1)新建工程,窗口类的名称为 MainWidget。

2)代码

mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include <QPushButton>

class MainWidget : public QWidget
{
    Q_OBJECT

public:
    MainWidget(QWidget *parent = nullptr);
    ~MainWidget();
private:
    QPushButton btn1;
    QPushButton *btn2;
};
#endif // MAINWIDGET_H

mainwidget.cpp

#include "mainwidget.h"

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

    btn2 = new QPushButton;
    btn2->setParent(this);
    btn2->setText("abc");
    btn2->resize(50, 50);
    btn2->move(0, 100);

    this->resize(320, 240);

    connect( &btn1, &QPushButton::clicked, this, &QWidget::close );
    /*
     * &b1:信号发出者,指针类型
     * &QPushButton::clicked:处理的信号。  &发送者的信号::信号名称
     * this:信号接收者
     * &QWidget::close:槽函数,信号处理函数
    */
}

MainWidget::~MainWidget()
{
}

 

3)实验现象:点击close按钮会关闭窗口,点击abc无反应。

 

自定义信号和槽

类比软件中断和中断响应。

1. 自定义槽

自定义槽(基本等于普通函数的用法)

  • Qt5的槽函数可以是:任意的成员函数,普通全局函数,静态函数
  • 槽函数需要和信号一致(参数,返回值)
  • 由于信号都是没有返回值,所以,槽函数也一定没有返回值

示例:创建一个工程,点击按键,按键显示变为 " Hello! "。用自定义槽的方法实现。

1)新建工程,窗口类的名称为 MainWidget。

2)代码

mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include <QPushButton>

class MainWidget : public QWidget
{
    Q_OBJECT

public:
    MainWidget(QWidget *parent = nullptr);
    ~MainWidget();

    void MySlot();

private:
    QPushButton btn1;
    QPushButton *btn2;
};
#endif // MAINWIDGET_H

mainwidget.cpp

#include "mainwidget.h"

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

    btn2 = new QPushButton;
    btn2->setParent(this);
    btn2->setText("abc");
    btn2->resize(50, 50);
    btn2->move(0, 100);

    this->resize(320, 240);

    connect( &btn1, &QPushButton::clicked, this, &MainWidget::close );
    /*
     * &b1:信号发出者,指针类型
     * &QPushButton::clicked:处理的信号。  &发送者的信号::信号名称
     * this:信号接收者
     * &QWidget::close:槽函数,信号处理函数
    */

    /*
     * 自定义槽(基本等于普通函数的用法)
     * Qt5的槽函数可以是:任意的成员函数,普通全局函数,静态函数
     * 槽函数需要和信号一致(参数,返回值)
     * 由于信号都是没有返回值,所以,槽函数一定没有返回值
    */
    connect( btn2, &QPushButton::clicked, this, &MainWidget::MySlot );
    connect( btn2, &QPushButton::clicked, &btn1, &QPushButton::hide );// 隐藏
}

void MainWidget::MySlot()
{
    btn2->setText("Hello!");
}

MainWidget::~MainWidget()
{
}

3)现象:

点击 " close ",关闭窗口。

点击 " abc ",此按钮显示文字变为 " Hello! ",并且会隐藏 " close "。

    

 

 

2. 自定义信号

自定义信号:

  • 信号必须有signals关键字来声明。
  • 信号没有返回值,但可以有参数。
  • 信号就是函数的声明,只需声明,无需定义。
  • 使用方法:emit 函数名();

示例需求:总共有两个窗口,一父窗口一子窗口,每次只显示一个。每个界面上都有一个 "切换窗口" 按钮,两个窗口通过按按键来回切换。(通过隐藏自己,显示另一个窗口来实现)

要求:(子窗口的属性为pritive,主窗口不能直接调用,要通过将按键事件包装成信号,与父窗口的槽形成关联)

1)新建一个窗口,新建类:工程,右键 - Add New...,选择 C++ Class。

 

2)代码:

subwidget.h

#ifndef SUBWIDGET_H
#define SUBWIDGET_H

#include <QWidget>
#include <QPushButton>

class SubWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SubWidget(QWidget *parent = nullptr);

    void sendSlot();

signals:
    /*
     * 信号必须有signals关键字来声明
     * 信号没有返回值,但可以有参数
     * 信号就是函数的声明,只需声明,无需定义
     * 使用:emit mySignal();
    */

    void mySignal();

private:
    QPushButton btn1;
};

#endif // SUBWIDGET_H

subwidget.cpp

#include "subwidget.h"

SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
    btn1.setParent(this);
    btn1.setText("切换窗口");
    btn1.resize(80, 50);
    btn1.move(20, 20);

    setWindowTitle("02");
    resize(200, 200);
    // 没有show,由MainWidget中的按钮触发

    connect( &btn1, &QPushButton::clicked, this,  &SubWidget::sendSlot);

    //直接这样写也是可以的,程序同样可以正常运行,emit本来就是一个空的宏定义,# define emit
    //connect( &btn1, &QPushButton::clicked, this,  &SubWidget::mySignal);
}

void SubWidget::sendSlot()
{
    emit mySignal();
}

mainwidget.h

#ifndef SUBWIDGET_H
#define SUBWIDGET_H

#include <QWidget>
#include <QPushButton>

class SubWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SubWidget(QWidget *parent = nullptr);

    void sendSlot();

signals:
    /*
     * 信号必须有signals关键字来声明
     * 信号没有返回值,但可以有参数
     * 信号就是函数的声明,只需声明,无需定义
     * 使用:emit mySignal();
    */

    void mySignal();

private:
    QPushButton btn1;
};

#endif // SUBWIDGET_H

mainwidget.cpp

#include "mainwidget.h"

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

    btn2 = new QPushButton;
    btn2->setParent(this);
    btn2->setText("abc");
    btn2->resize(50, 50);
    btn2->move(0, 100);

    btn3.setParent(this);
    btn3.setText("切换窗口");
    btn3.resize(80, 50);
    btn3.move(100, 0);

    resize(320, 240);
    setWindowTitle("01");

    connect( &btn1, &QPushButton::clicked, this, &MainWidget::close );
    /*
     * &b1:信号发出者,指针类型
     * &QPushButton::clicked:处理的信号。  &发送者的信号::信号名称
     * this:信号接收者
     * &QWidget::close:槽函数,信号处理函数
    */

    /*
     * 自定义槽(基本等于普通函数的用法)
     * Qt5的槽函数可以是:任意的成员函数,普通全局函数,静态函数
     * 槽函数需要和信号一致(参数,返回值)
     * 由于信号都是没有返回值,所以,槽函数一定没有返回值
    */
    connect( btn2, &QPushButton::clicked, this, &MainWidget::mySlot );
    connect( btn2, &QPushButton::clicked, &btn1, &QPushButton::hide );// 隐藏

    // 点击01窗口的"切换窗口",会显示02窗口,并将01隐藏
    connect( &btn3, &QPushButton::clicked, this, &MainWidget::changeWin );

    // 点击02窗口的"切换窗口",会显示01窗口,并将02隐藏
    connect( &w2, &SubWidget::mySignal, this, &MainWidget::dealSub );

    // 因为main里已经有show了,这里可以不写show。
}

void MainWidget::mySlot()
{
    btn2->setText("Hello!");
}

void MainWidget::changeWin()
{
    // 本窗口隐藏
    this->hide();
    // 子窗口显示
    w2.show();
}

void MainWidget::dealSub()
{
    // 子窗口隐藏
    w2.hide();
    // 本窗口显示
    this->show();
}

MainWidget::~MainWidget()
{
}

 

3)现象:每次只显示一个窗口,点击切换窗口,会在两个窗口间切换。

    

 

注:一个信号可以关联多个槽,不过不建议这么做,不利于后期阅读。尽量只关联一个槽函数,在槽函数中去实现。

注:emit其实是空宏定义,而且实际代码中,即使发送信号不加emit,程序依然可以正常运行。详细说明:https://blog.csdn.net/qq_27312943/article/details/50789914

不过估计这个宏还是有意义的,应该在qmake源码里,只不过我们看不到它根据这个宏做了哪些处理

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值