QT —— 信号和槽(自定义信号和槽函数)
QT —— 信号和槽(自定义信号和槽函数)
- 自定义信号和槽函数
- 一、自定义信号函数规范
- 1. 声明位置
- 2. 返回值与实现
- 3. 参数与重载
- 二、自定义槽函数规范
- 1. 声明位置(不同版本差异)
- 2. 返回值与实现
- 3. 参数与重载
- 三、信号发射规范
- 1. 基本用法
- 2. 为什么要用emit
- 四、完整示例
之前我们简单了解了一下信号和槽,没有看过上一节的小伙伴可以看一下:
https://blog.csdn.net/qq_67693066/article/details/147275998?sharetype=blogdetail&sharerId=147275998&sharerefer=PC&sharesource=qq_67693066&spm=1011.2480.3001.8118
我们上一节大多使用的是按钮自带的信号或者槽函数,其实我们可以自己定义信号和槽函数。
自定义信号和槽函数
在Qt中自定义信号和槽函数需要遵循特定的语法规范:
一、自定义信号函数规范
1. 声明位置
- 必须声明在类的
signals:
区块下 - 示例:
class MyClass : public QObject {Q_OBJECT signals: // 信号声明区void mySignal();void dataReceived(const QByteArray &data); };
2. 返回值与实现
- 必须返回
void
类型 - 只需声明,不需要实现(由moc自动生成实现)
- 错误示例:
signals:int invalidSignal(); // 错误!信号必须返回voidvoid anotherSignal() { /* 实现 */ } // 错误!信号不能有实现
3. 参数与重载
- 可以带参数,支持重载
- 示例:
signals:void valueChanged(int newValue);void valueChanged(double newValue); // 重载信号
二、自定义槽函数规范
1. 声明位置(不同版本差异)
-
Qt4及早期版本:
class MyClass : public QObject {Q_OBJECT public slots: // 必须声明在slots区块void mySlot(); };
-
Qt5及以后版本:
class MyClass : public QObject {Q_OBJECT public: // 可以声明在public区域void mySlot(); // 可作为槽函数 };
2. 返回值与实现
- 通常返回
void
(但也可以有返回值) - 必须提供实现
- 示例:
// 声明 public slots:void processData(const QString &data);int computeResult(); // 允许但不推荐// 实现 void MyClass::processData(const QString &data) {// 实现代码 }
3. 参数与重载
- 可以带参数,支持重载
- 示例:
public slots:void setValue(int value);void setValue(double value); // 重载槽
三、信号发射规范
1. 基本用法
- 使用
emit
关键字(实际是可选的宏) - 示例:
void MyClass::updateValue(int val) {m_value = val;emit valueChanged(val); // 推荐使用emitvalueChanged(val); // 这样也可以,但不推荐 }
2. 为什么要用emit
- 代码可读性:明确标识这是信号发射点
- 开发提示:提醒开发者这是跨对象的通信点
- 虽然不是强制要求,但是良好的编程习惯
四、完整示例
我们可以来试一下,我已经加了一个我自己定义的信号:
现在我们到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::handler);emit MySignal();}void Widget::handler()
{qDebug() << "这是我自己定义的槽函数";
}Widget::~Widget()
{delete ui;
}
这里要注意一下顺序:
原因是,首先关联信号和槽,一旦检测到信号发射之后就会立马执行关联的槽函数。反之,若先发射信号,此时还没有关联槽函数,当信号发射之后槽函数不会响应。
我们再来写一个例子:当老师说"上课了",学生们就"回到座位,开始学习":
在teacher.h中声明信号函数:
在student.h中声明槽函数:
在widget.h中实例化"老师类对象"和"学生类对象";
在student.cpp中实现槽函数:
在widget.cpp中连接⾃定义信号和槽;