一、自定义信号和槽

实现功能:定义两个类,mysignal类,myslot类。mysignal类发出信号hello,myslot响应信号打印Hello World。

(1)创建类

首先右键项目-添加新文件-创建新的C++类,基类选择QObject。

(2)自定义信号和槽函数

自定义信号写到signals下。返回值是void,只需要声明,不需要实现。可以有参数,可以重载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//mysignal.h
#ifndef MYSIGNAL_H
#define MYSIGNAL_H

#include <QObject>

class MySignal : public QObject
{
Q_OBJECT
public:
explicit MySignal(QObject *parent = nullptr);

signals:
void hello(); //添加了自定义信号

public slots:
};

#endif // MYSIGNAL_H

自定义槽函数写在public slots下。返回值是void,需要声明,也需要实现。可以有参数,可以重载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//myslot.h
#ifndef MYSLOT_H
#define MYSLOT_H

#include <QObject>

class MySlot : public QObject
{
Q_OBJECT
public:
explicit MySlot(QObject *parent = nullptr);

signals:

public slots:
void printhello(); //添加了自定义槽
};

#endif // MYSLOT_H

实现槽函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//myslot.cpp
#include "myslot.h"
#include <QDebug> //QDebug可在底部打印输出字符串

MySlot::MySlot(QObject *parent) : QObject(parent)
{

}

// 自定义槽函数实现
void MySlot::printhello()
{
qDebug("Hello World!"); //输出HelloWorld
}

(3)创建两个类的对象并使用connect进行连接

首先在widget.h中声明两个类的指针,然后在widget.cpp中new两个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QMainWindow>
#include "mysignal.h" //引入两个类的头文件
#include "myslot.h"

namespace Ui {
class widget;
}

class widget : public QMainWindow
{
Q_OBJECT

public:
explicit widget(QWidget *parent = 0);
~widget();

private:
Ui::widget *ui;
MySignal * mysignal; //声明两个类的指针
MySlot * myslot;
};

#endif // WIDGET_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//widget.cpp
#include "widget.h"
#include "ui_widget.h"

widget::widget(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::widget)
{
ui->setupUi(this);

this->mysignal = new MySignal; //new两个对象
this->myslot = new MySlot;
connect(mysignal, &MySignal::hello, myslot, &MySlot::printhello);
}

widget::~widget()
{
delete ui;
}

(4)创建触发函数

只有上面的代码,虽然创建了两个类,也定义了信号和槽函数,但是缺少触发条件,此时运行程序,程序无反应。

在widget.h的widget类的private中声明触发函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef WIDGET_H
#define WIDGET_H

#include <QMainWindow>
#include "mysignal.h"
#include "myslot.h"

namespace Ui {
class widget;
}

class widget : public QMainWindow
{
Q_OBJECT

public:
explicit widget(QWidget *parent = 0);
~widget();

private:
Ui::widget *ui;
MySignal * mysignal;
MySlot * myslot;
void mytrigger();
};

#endif // WIDGET_H

在widget.cpp下方定义触发函数,并在widget中添加触发函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "widget.h"
#include "ui_widget.h"

widget::widget(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::widget)
{
ui->setupUi(this);

this->mysignal = new MySignal;
this->myslot = new MySlot;
connect(mysignal, &MySignal::hello, myslot, &MySlot::printhello);
mytrigger();
}

void widget::mytrigger()
{
emit mysignal->hello();
}

widget::~widget()
{
delete ui;
}

二、信号的连接与断开

2.1 信号连接信号

connect不仅可以连接信号与槽,也可以连接信号与信号,实现当触发一个信号时,由该信号继续触发另一个信号。

1
connect(btn, &QPushButton::clicked, mysignal, &MySignal::hello);

2.2 信号与槽断开

断开信号使用disconnect关键字,其参数与connect完全相同。

1
disconnect(btn, &QPushButton::clicked, mysignal, &MySignal::hello)