Qt5教程: (3) 自定义信号与槽

1. 自定义槽

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

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

void MainWidget::mySlot()
{
    b2->setText("^_^");
}

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

connect(b2, &QPushButton::clicked, this, &MainWidget::mySlot);

保存后运行, 点击Button2就会变成笑脸了:

附录

mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include <QPushButton>

class MainWidget : public QWidget
{
    Q_OBJECT

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

public slots:
    void mySlot();

private:
    QPushButton b1;
    QPushButton *b2;
};

#endif // MAINWIDGET_H

mainwidget.cpp

#include "mainwidget.h"

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

    b2 = new QPushButton(this);
    b2->setText("Button2");
    b2->move(150, 50);

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

    connect(b2, &QPushButton::clicked, this, &MainWidget::mySlot);

}

void MainWidget::mySlot()
{
    b2->setText("^_^");
}

MainWidget::~MainWidget()
{

}

2. 自定义信号

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

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

之后修改Button2的文本"Button2"为"Next"
新建一个窗口
右键工程目录"SignalAndSlot" --> Add New:

选择 C++ --> C++ Class --> Choose:

输入Class name为SubWidget, Base class为QWidget, 点击Next, 点击Finish:

之后一个新的窗口类就新建好了:

修改新窗口的标题:
在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);

保存后运行, 现在可以在两个界面中切换了.

附录

mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include <QPushButton>
#include "subwidget.h"

class MainWidget : public QWidget
{
    Q_OBJECT

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

public slots:
    void nextSlot();
    void backSlot();

private:
    QPushButton b1;
    QPushButton *b2;

    SubWidget subWin;
};

#endif // MAINWIDGET_H

mainwidget.cpp

#include "mainwidget.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    this->setWindowTitle("Window1");
    this->resize(300, 200);
    b1.setParent(this);
    b1.setText("Close");
    b1.move(50, 50);

    b2 = new QPushButton(this);
    b2->setText("Next");
    b2->move(150, 50);

    connect(&b1, &QPushButton::clicked, this, &MainWidget::close);
    connect(b2, &QPushButton::clicked, this, &MainWidget::nextSlot);
    connect(&subWin, &SubWidget::backSignal, this, &MainWidget::backSlot);

}

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

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

MainWidget::~MainWidget()
{

}

subwidget.h

#ifndef SUBWIDGET_H
#define SUBWIDGET_H

#include <QWidget>
#include <QPushButton>

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

signals:
    void backSignal();

public slots:
    void sendSignal();

private:
    QPushButton b;
};

#endif // SUBWIDGET_H

subwidget.cpp

#include "subwidget.h"

SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("Windows2");
    this->resize(300, 200);

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

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

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


此文原创禁止转载,转载文章请联系博主并注明来源和出处,谢谢!
作者: Raina_RLN https://www.cnblogs.com/raina/

posted @ 2019-08-07 14:05  Raina_R  阅读(14703)  评论(0编辑  收藏  举报