本节对应的视频讲解:B_站_链_接

https://www.bilibili.com/video/BV1gA4y1d7gz

上节课,我们讲解了标准信号槽,标准信号槽中,信号和槽函数,都是 Qt 框架定义好的。

Qt 还允许我们自定义信号和槽。

自定义信号和槽的条件:

  • 自定义的类,要继承自 QObject
  • 自定义的类,其中要声明一个宏 Q_OBJECT

只有满足了这两个条件才可以正常使用信号槽机制(当然,槽函数是全局函数、 Lambda 表达式等无需接收者的时候除外,后边讲解)。

1. 自定义信号槽案例


接下来,我们通过一个案例,演示自定义信号槽的使用。

案例:“长官” (Commander)发送一个 “冲” (go) 的信号,然后 “士兵" (Soldier)执行“ 战斗” (fight) 的槽函数

1.1 创建 Commander 类

在左侧项目文件名上右键 -> 添加新文件:

指定类名和父类

点击完成,即可添加cpp和.h文件到项目中

创建完成之后的 commander.cppcommander.h 文件,内容如下:

// commander.h
#ifndef COMMANDER_H
#define COMMANDER_H#include <QObject>// 1.自定义的类,需要继承自 QObject 类
class Commander : public QObject
{// 2.并且添加 Q_OBJECT 宏,才能正常使用 Qt 的信号和槽机制Q_OBJECT
public:explicit Commander(QObject *parent = nullptr);
// 3.在 signals 后面添加自定义的信号即可
signals:};#endif // COMMANDER_H// commander.cpp
#include "commander.h"Commander::Commander(QObject *parent): QObject{parent}
{}

1.2 添加自定义信号

signals 下面添加自定义的信号即可

class Commander : public QObject
{Q_OBJECT
public:explicit Commander(QObject *parent = nullptr);signals:// 1.信号只需声明,无需实现// 2.信号返回值为 voidvoid go();
};

1.3 添加 Soldier 类

按照同样的方法,添加 Soldier 类,创建完成之后的 soldier.hsoldier.cpp 文件,内容如下:

// soldier.h
#ifndef SOLDIER_H
#define SOLDIER_H#include <QObject>class Soldier : public QObject
{Q_OBJECT
public:explicit Soldier(QObject *parent = nullptr);signals:};#endif // SOLDIER_H// soldier.cpp
#include "soldier.h"Soldier::Soldier(QObject *parent): QObject{parent}
{}

1.4 添加自定义槽

Soldier 士兵类,需要实现一个 fight 的槽函数

class Soldier : public QObject
{Q_OBJECT
public:explicit Soldier(QObject *parent = nullptr);signals:// 1.通常将槽函数添加到 slots 后面
// 这个 slots 也可以不写。不过建议写上,以指明这是一个槽函数
// pulic,表示槽函数既可以在当前类及其子类的成员函数中调用,也可以在类外部的其它函数(比如 main() 函数)中调用
public slots:// 2.槽函数的返回值和参数,要和信号保持一致// 由于信号无返回值,因此槽函数也无返回值// 由于信号无参数,因此槽函数也无参数void fight();
};

soldier.h 文件中有了槽函数的声明,还需要在 soldier.cpp 中实现

可以在槽函数声明处,直接按 alt + enter 快捷键,快速生成函数定义

void Soldier::fight()
{qDebug() << "fight";
}

1.5 连接自定义的信号和槽

信号和槽都已经定义完毕, 接下来就可以进行连接了

mainwindow.cpp 中,定义 CommanderSoldier 类的实例,并建立信号和槽的连接,如下:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1. 创建两个类的实例Commander commander;Soldier soldier;// 2. 建立信号和槽的连接connect(&commander, SIGNAL(go()), &soldier, SLOT(fight()));// 3. 发送信号// emit 可省略/*emit*/commander.go();
}

这样,在程序执行后,就可以在【应用程序输出】窗口看到槽函数执行的结果了:

1.6 信号和槽的重载

我们知道,信号和槽的本质就是函数,是函数就可以重载,因此,我们可以重载同名的信号,和重载同名的槽函数。

仍然以 CommanderSoldier 为例:

commander.h 中添加重载的 go 信号:

class Commander : public QObject
{Q_OBJECT
public:explicit Commander(QObject *parent = nullptr);signals:void go();void go(QString);
};

soldier.h 中添加重载的fight槽函数:

class Soldier : public QObject
{Q_OBJECT
public:explicit Soldier(QObject *parent = nullptr);signals:public slots:void fight();void fight(QString);
};

soldier.cpp 中实现重载的fight槽函数:

void Soldier::fight(QString s)
{qDebug() << "fight for" << s;
}

接下来在mainwindow.cpp中同时发送重载的两个go信号:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 1. 创建两个类的实例Commander commander;Soldier soldier;// 2. 建立信号和槽的连接connect(&commander, SIGNAL(go()), &soldier, SLOT(fight()));connect(&commander, SIGNAL(go(QString)), &soldier, SLOT(fight(QString)));// 3. 发送信号commander.go();commander.go("freedom");
}

此时执行程序,就可以在【应用程序输出】窗口看到两个重载的槽函数执行的结果了:

2. 信号槽总结


2.1 使用信号和槽的条件

如果要使用信号和槽,需要满足如下两个条件

  • 自定义的类,要继承自 QObject
  • 自定义的类,其中要声明一个宏 Q_OBJECT

只有满足了这两个条件才可以正常使用信号槽机制。

2.2 信号

  • 无需实现
    信号的本质是函数,并且只需要声明,不需要实现;
  • 可以重载
    信号本质是函数,因此可以重载;
  • 信号声明在类头文件的 signals 域下;
  • 信号返回值类型为 void,参数的类型和个数不限;
  • 信号可以使用 emit 关键字发射,emit 也可以省略;

2.3 槽

  • 需要实现
    槽的本质是函数,需要实现;
  • 可以重载
    槽本质是函数,因此可以重载;
  • 槽函数用 slots 关键字修饰(其实在 Qt5 中可以省略 slots 关键字,下一节会讲解);
  • 返回值
    槽函数的返回值,要和信号保持一致。由于信号的返回值为 void,因此槽函数的返回值也是 void
  • 参数
    槽函数的参数个数要 <= 信号的参数个数
    也就是说:可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少),但是不能说信号根本没有这个数据,你就要在槽函数中使用(就是槽函数的参数比信号的多,这是不允许的)

本节对应的视频讲解:B_站_链_接
https://www.bilibili.com/video/BV1gA4y1d7gz

【QT开发笔记-基础篇】| 第一章 QT入门 | 1.6 自定义信号槽相关推荐

  1. 【QT开发笔记-基础篇】| 第二章 常用控件 | 2.12 表格控件 QTableWidget

    本节对应的视频讲解:B_站_链_接 QTableWidget 是 Qt 中的表格控件,可以行列的形式来展示数据 1. 属性和方法 QTableWidget 有很多属性和方法,完整的可查看帮助文档. 在 ...

  2. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.1 为什么要学习Qt

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1334y1776z Qt 是一个跨平台的 C++ 图形用户界面应用程序框架 Qt 为应用程序开发 ...

  3. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.2 搭建Qt开发环境

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1Pr4y1x7fh Qt 开发主要有两种开发环境 Qt Creator 它是 Qt 官方提供的开 ...

  4. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.4 项目构建流程

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1cW4y1y7Lw 在上一节课中,我们新建了第一个 Qt 工程,其中包括 5 个文件: Hell ...

  5. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.7 如何连接信号槽

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1mN4y137H6 信号和槽要建立连接,本质上是通过 `connect` 函数来连接实现的. 但 ...

  6. 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.5 标准信号槽

    本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1vW4y1676Q 本节讲解信号和槽的概念,以及标准的信号槽 1. 什么是信号槽 1.1 信号 ...

  7. 【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.1 效果演示、技术点

    本节对应的视频讲解:B_站_视_频 https://www.bilibili.com/video/BV14P4y197pi Qt 中绘图用到的类是 QPainter,可以实现点.线.矩形.圆形.多边形 ...

  8. 【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.5 多段线、多边形

    本节对应的视频讲解:B_站_视_频 https://www.bilibili.com/video/BV1ZP4y1S7Ax 本节讲解如何绘制多段线.多边形 1. 相关的 API 直接查看官方的帮助文档 ...

  9. 【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.12 文本、图片

    本节对应的视频讲解:B_站_视_频 https://www.bilibili.com/video/BV1k14y1A7XL 本节讲解如何绘制文本 1. 相关的 API 直接查看官方的帮助文档,可以看到 ...

最新文章

  1. 2017年如何在移动端优雅的使用flex
  2. 自定义取值距离的javascript random()函数
  3. thinkPHP增删改查的方法案例
  4. android studio 集成 第三方sdk,Android FrameWork集成第三方SDK的jar包和so庫
  5. 40 SD配置-销售凭证设置-分配计划行类别
  6. python课设答辩问题及答案_HTML5网站前端开发设计答辩问题及答案
  7. Oracle体系概要
  8. DeFi 协议 Benchmark Protocol 启动第二阶段流动性挖矿计划 The Press
  9. 线性回归-最小二乘python实现
  10. 电信、联通合建 5G,将会碰出怎样的火花?
  11. Moment.js 一款JS时间封装库
  12. java计算器流程图_我的第一个JAVA程序之计算器
  13. nb模块不能接收公网消息_NB-IoT 对接调测问题汇总,你想知道的都在这儿 | 收藏吧...
  14. 办公自动化:PDF文件合并器,将多个PDF文件进行合并...
  15. 业务安全情报第四期:新能源车企重金打造的私域流量,成为黑灰产“掘金发财”的新目标
  16. JVM-什么是GC?
  17. 拼写检查工具是android,Android拼写检查器
  18. linux查看进程limits解释,linux中/etc/security/limits.conf配置文件说明
  19. 笔记记录软件:NoteRecorder
  20. mathtype 7.4安装教程

热门文章

  1. UpdateData(TRUE)与UpdateData(FALSE)用法
  2. Google Map开发系列(六)——谷歌地图坐标定位
  3. 求任意一个正整数的二进制中有多少个比特位为1
  4. 浙江大学计算机科学与技术学院导师,浙江大学计算机科学与技术专业导师介绍:徐从富...
  5. 华为与小米赛跑-续!!华为四款新机上市
  6. Flask操作指南,留着练习
  7. STM32F103系列(三):初识STM32F103
  8. 如何确认某日是否为工作日(休息日)
  9. AIDA64压力测试教程,AIDA64压力测试多长时间,AIDA64压力测试结果怎么看
  10. 谷粒学院(二十四)Jenkins+Maven+Github+Springboot实现可持续自动部署(非常详细)