之前我们简单了解了一下信号和槽,没有看过上一节的小伙伴可以看一下:

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();  // 错误!信号必须返回void
        void 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);  // 推荐使用emit
        valueChanged(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中连接⾃定义信号和槽;
在这里插入图片描述
在这里插入图片描述

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐