当前位置: 首页 > news >正文

【Qt】8.信号和槽_自定义信号和槽​

文章目录

  • 1. 自定义信号和槽
    • 1.1 基本语法
    • 1.2实例
    • 1.3 带参数的信号和槽


1. 自定义信号和槽

1.1 基本语法

Qt中也允许自定义信号:

自定义槽函数,非常关键,开发中大部分情况都是需要自定义槽函数的槽函数,就是用户触发某个操作之后,要进行的业务逻辑

自定义信号,比较少见,实际开发中很少会需要自定义信号。

信号就对应到用户的某个操作。在GUI,用户能够进行哪些操作,是可以穷举的。

Qt内置的信号,基本上已经覆盖到了上述所有可能的用户操作。因此,使用Qt内置的信号,就足以应付大部分的开发场景了。

自定义信号,本身代码比较简单的。

1、自定义信号函数书写规范

  1. 自定义信号函数必须写到 “signals” 下;
  2. 返回值为 void,只需要声明,不需要实现;
  3. 可以有参数,也可以发生重载;

2、自定义槽函数书写规范

  • 早期的 Qt 版本要求槽函数必须写到 “public slots” 下,但是现在高级版本的 Qt 允许写到类的
  • public” 作用域中或者全局下;返回值为 void,需要声明,也需要实现;
  • 可以有参数,可以发生重载;

3、发送信号

使用 “emit” 关键字发送信号 。“emit” 是一个空的宏。“emit” 其实是可选的,没有什么含义,只是为了提醒开发人员。

咱们的Widget虽然还没有定义任何信号,由于继承自QWidget,和QObject,这俩类里面已经提供了一些信号了,可以直接使用。

所谓的Qt的信号,本质上也就是一个“函数”。

Qt5以及更高版本中,槽函数和普通的成员函数之间,没啥差别了。

但是,信号,则是一类非常特殊的函数。

  1. 程序员只要写出函数声明,并且告诉Qt,这是一个“信号”即可。

    这个函数的定义,是Qt在编译过程中,自动生成的。(自动生成的过程,程序员无法干预)

    信号在Qt中是特殊的机制。Qt生成的信号函数的实现,要配合Qt框架做很多既定的操作。

  2. 作为信号函数,这个函数的返回值,必须是void
    有没有参数都可以,甚至也可以支持重载。
    signals:
    这个也是Qt自己扩展出来的关键字,qmake的时候,调用一些代码的分析/生成工具。
    扫描到类中包含signals这个关键字的时候,此时,就会自动的把下面的函数声明认为是信号,并且给这些信号函数自动的生成函数定义。


1.2实例

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();signals:void mySignal();public:void handleMySignal();private:Ui::Widget *ui;
};
#endif // WIDGET_H

widget.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::handleMySignal);
}Widget::~Widget()
{delete ui;
}void Widget::handleMySignal()
{this->setWindowTitle("处理自定义信号");
}

运行后:

6ad1af5f6389d0e9e79784c95902628e

为啥呢?因为只建立了连接,没有发送信号。

connect(this,&Widget::mySignal,this,&Widget::handleMySignal);

建立连接,不代表信号发出来了。

如何才能触发出自定义的信号呢?

Qt内置的信号,都不需要咱们手动通过代码来触发。

用户在GUI,进行某些操作,就会自动触发对应信号。(发射信号的代码已经内置到Qt框架中了)

Qt提供了一个关键字:emit(发射)

通过emit mySignal();就可以触发对应的信号。

0bff2d96bf6ab13791407fb31d17a2df

也不一定要在构造函数里面搞,弄到按钮里面就是点击按钮,发送自定义操作。

6216132627fac4ebb74ef47963b8faa9

65906856fdb5b6b69b6ec349b7b42f11

使用过程:
点击按钮--->QPushButton:clicked--->Widget::on_pushButton_clicked()--->emit mySignal();--->void Widget::handleMySignal()

其实在Qt 5emit 现在啥都没做。真正的操作都包含在mySignal内部生成的函数定义了

即使不写emit,信号也能发出去。

刚刚的:void Widget::on_pushButton_clicked()里面不写emit,也可以发送

即使如此,实际开发中,还是建议把emit都加上。

加上代码可读性更高,更明显的标识出,这里是发射自定义的信号了。当然内置的信号也可以发送。


1.3 带参数的信号和槽

Qt 的信号和槽也支持带有参数, 同时也可以支持重载。

此处我们要求, 信号函数的参数列表要和对应连接的槽函数参数列表一致。

此时信号触发, 调用到槽函数的时候, 信号函数中的实参就能够被传递到槽函数的形参当中。

通过这样的机制, 就可以让信号给槽传递数据了。

signals:void mySignal(const QString&);public:void handleMySignal(const QString&);

这里的参数必须要一致。

一致主要是要求类型,个数如果不一致也可以。

不一致的时候,要求信号的参数的个数必须要比槽的参数个数要更多。

C++中声明函数的时候,形参的名字可以不必写。

f81f7811018acec9e6ec83653c961c77

text也就是带参数的信号

运行:

3b39b2a58f81e54e7ab57bb108dc10f7

点击:

e6c2d87ed481004d69c0c5c5cd0ee56b

传参可以起到复用代码的效果。

有多个逻辑,逻辑上整体一致,但是涉及到的数据不同,就可以通过函数-参数来复用代码,并且在不同的场景中传入不同的参数即可

signals:void mySignal(const QString& text);public:void handleMySignal(const QString& text);

改完后,运行:

6ff5967b5df52ea3228a3b70b78d088a

点击按钮1:

4a16476701f91cb94598adaa9d6186fc

点击按钮2:

7c640bf601b4444ac0047502846735d2

通过这一套信号槽,搭配不同的参数,就可以起到设置不同标题的效果。

connect(this,&Widget::mySignal,this,&Widget::handleMySignal);

Qt中很多内置的信号,也是带有参数的。(这些参数不是咱们自己传递的)

clicked信号就带有一个参数,bool

这个参数表示当前按钮是否处于“选中”状态。

这个选中状态对于QPushButton没啥意义,对于QCheckBox复选框,就很有用了。

然后给信号函数加个参数

signals:void mySignal(const QString& text,const QString& text2);public:void handleMySignal(const QString& text);

0f16635eb8685b8eee1ac55247e41955

但是反过来就不行

a254974c5d46ec8e992d5598528f89ae

直观的思考,应该是要求信号的参数个数和槽的参数个数,严格一致,此处为啥允许信号的参数比槽的参数多呢??

一个槽函数,有可能会绑定多个信号。

如果我们严格要求参数个数一致,就意味着信号绑定到槽的要求就变高了。

换而言之,当下这样的规则,就允许信号和槽之间的绑定更灵活了,更多的信号可以绑定到这个槽函数上了。

个数不一致,槽函数就会按照参数顺序,拿到信号的前N个参数。

至少需要确保,槽函数的每个参数都是有值的。

61c74fa144c0343acc61a8c509836fb3

然后我们来改一下代码:

50f5813de454e8d9f31efedce4d4a15f

8eee52ea8c2f19ee3ce65bc86744c1b2

可以看到编译报错的,因为带有参数的信号,要求信号的参数和槽的参数要一致

类型,个数要满足要求(信号的参数个数要多于槽的参数个数)

afc2ae09e511a87cf64b71dfdd625c53

展开的代码还可以展开,最终展开的效果会得到一系列很复杂的代码

这些代码就涉及到Qt实现的内部原理了。(此处就不去深入研究了)

如果不加这个宏,这个类在编译的时候也会出错!

5a058413e3b2766654410b76cbf0adc1

http://www.dtcms.com/a/490356.html

相关文章:

  • WPF——动画
  • 医院做网站怎么做wordpress还能用
  • YOLO系列目标检测算法全面解析
  • 目标检测全解析:从基础概念到深度学习实战技术
  • 基于深度学习计算机视觉的风格迁移技术原理与经典实现解析
  • Redis Key设计与Value存储
  • Pytest+requests进行接口自动化测试8.0(Allure进阶 + 文件上传接口 + 单接口多用例)
  • Kubernetes全景解读:从云原生基石到卓越实践
  • 【JUnit实战3_02】第二章:探索 JUnit 的核心功能(一)
  • 计算机视觉(opencv)——实时颜色检测
  • 宣传网站怎么做网站制作洋网络
  • 网站排名优化化快排优化网站服务器搭建的步骤
  • 本地用docling实现pdf转markdown操作笔记
  • iOS 26 APP 性能测试实战攻略:多工具组合辅助方案
  • 《Linux运维总结:基于X86_64+ARM64架构CPU使用docker-compose一键离线部署consul 1.21.5容器版集群》
  • wordpress 购物东莞网站优化方法有哪些
  • 接线盒工程量-图形识别高效运算
  • 后厨手套穿戴检测保障食品安全 手套佩戴检测 未戴手套检测 未佩戴手套实时报警 高危行业手套佩戴实时监控
  • 原位PL光谱测试教学(实操版)
  • 技术报告:高仿真虚构内容对主流大模型的现实感幻觉测试
  • 大模型提示词简介
  • R语言术语(2)
  • 广州网站建设推广谷歌官网首页
  • 【Python】基于Tkinter库实现文件夹拖拽与选择功能
  • Spring Boot 官方文档精解:构建与依赖管理
  • ONLYOFFICE 桌面编辑器9.1版本已发布:PDF密文功能和全新注释、工作表公式优化及文件恢复便捷化等
  • 重视网站阵地建设广州市天河区建设局官方网站
  • QPS、TPS、RPS 详解
  • 零基础从头教学Linux(Day 50)
  • 《计算机操作系统》_理解并发程序的执行_第4次课20250925