Qt自定义信号槽的使用浅析+实例
1. Qt中自定义信号槽的使用
Qt框架提供的信号槽在某些特定场景下是无法满足我们的项目需求的,因此我们还设计自己需要的的信号和槽,使用connect()对自定义的信号槽进行连接。
如果想要使用自定义的信号槽, 首先要编写新的类并且让其继承Qt的某些标准类,我们自己编写的类想要在Qt中使用使用信号槽机制, 那么必须要满足的如下条件:
- 这个类必须从QObject类或者是其子类进行派生
- 在定义类的头文件中加入 Q_OBJECT 宏
1.1 自定义信号
要求:
1. 信号是类的成员函数
2. 返回值是 void 类型
3. 信号的名字可以根据实际情况进行指定
4. 参数可以随意指定, 信号也支持重载
5. 信号需要使用 signals 关键字进行声明, 使用方法类似于public等关键字
6. 信号函数只需要声明, 不需要定义(没有函数体实现)
7. 在程序中发送自定义信号: 发送信号的本质就是调用信号函数
- 习惯性在信号函数前加关键字: emit
- emit只是显示的声明一下信号要被发送, 没有特殊含义
- 底层 emit == #define emit
示例
class Test : public QObject
{
Q_OBJECT
signals:
void testsignal();
// 参数的作用是数据传递, 谁调用信号函数谁就指定实参
// 实参最终会被传递给槽函数
void testsignal(int a);
};
1.2 自定义槽
槽函数就是信号的处理动作,自定义槽函数和自定义的普通函数写法是一样的。
要求:
- 返回值是 void 类型
- 槽也是函数, 因此也支持重载
- 槽函数需要指定多少个参数, 需要看连接的信号的参数个数
- 槽函数的参数是用来接收信号发送的数据的, 信号发送的数据就是信号的参数
- 举例:
信号函数: void testsig(int a, double b);
槽函数: void testslot(int a, double b); - 总结:
槽函数的参数应该和对应的信号的参数个数, 类型一一对应
信号的参数可以大于等于槽函数的参数个数 == 信号传递的数据被忽略了
信号函数: void testsig(int a, double b);
槽函数: void testslot(int a);
这里槽函数只接受信号函数中的第一个参数
- Qt中槽函数的类型:
- 类的成员函数
- 全局函数
- 静态函数
- lambda表达式(匿名函数) - 槽函数可以使用关键字进行声明: slots (Qt5中slots可以省略不写)
- public slots:
- private slots:
- protected slots:
// 举例
// 类中的这三个函数都可以作为槽函数来使用
class Test : public QObject
{
public:
void testSlot();
static void testFunc();
public slots:
void testSlot(int id);
};
1.3 自定义信号槽实例
现在有一个场景,女朋友饿了,我请她吃饭,那么实现这个功能应该怎么做呢
首先明确发送者,接收者,信号和槽分别是哪些
- 发送者: 女朋友
- 接收者: 我
- 信号: 饿了
- 槽:请她吃饭
ok,明确了这些,接下来我们就可以开始写代码了
首先创建两个类,GirlFriend 和 Me
Qt Creator中会自动为我们添加头文件和CPP文件,目录结构如下图

- 在GirlFriend类中,添加信号hungry,代码如下
#ifndef GIRLFRIEND_H
#define GIRLFRIEND_H
#include <QObject>
class GirlFriend : public QObject
{
Q_OBJECT
public:
explicit GirlFriend(QObject *parent = nullptr);
signals:
void hungry();
};
#endif // GIRLFRIEND_H
注意图中的 signals关键字,这个就是用来定义信号的地方,信号函数只需要定义,不需要实现!
- 在Me这个类中添加槽函数eat();
#ifndef ME_H
#define ME_H
#include <QObject>
class Me : public QObject
{
Q_OBJECT
public:
explicit Me(QObject *parent = nullptr);
// 槽函数
public slots:
// 槽函数
void eat();
};
#endif // ME_H
注意!
这里用public slots主要是为了提醒开发者,这是一个槽函数,事实上,可以不用单独用public slots,可以直接将这个槽函数放到public中,与普通函数一样,槽函数不仅需要定义,也需要实现。
- 到me.cpp中实现Me类的槽函数eat()
#include "me.h"
#include <QDebug>
Me::Me(QObject *parent) : QObject(parent)
{
}
void Me::eat()
{
qDebug() << "带你去吃麻辣烫...";
}
ok,现在槽函数和信号函数都已经定义实现了,那怎么样实现事件的响应呢,一个简单的想法是,设置一个按钮,点击按钮发送信号:hungry,然后让eat()响应
到mainwindow中添加一个按钮Hungry,取名为hungry

如果这个时候出现在mainwindow.cpp中,无法识别这个按钮,可以参考我的这篇博客
Qt项目ui文件新添加的控件在代码中不识别的问题解决添加这个按钮后,我们需要在mainwindow类中添加两个成员指针

在mainwindow.cpp中通过connect函数来绑定
在这里我再复习一遍Qt中的 connect() 函数
QMetaObject::Connection QObject::connect(
const QObject *sender, PointerToMemberFunction signal,
const QObject *receiver, PointerToMemberFunction method,
Qt::ConnectionType type = Qt::AutoConnection);
- 参数:
- sender: 发出信号的对象
- signal: 属于sender对象, 信号是一个函数, 这个参数的类型是函数指针, 信号函数地址
- receiver: 信号接收者
- method: 属于receiver对象, 当检测到sender发出了signal信号,
receiver对象调用method方法,信号发出之后的处理动作
// connect函数相对于做了信号处理动作的注册
// 调用conenct函数的sender对象的信号并没有产生, 因此receiver对象的method也不会被调用
// method槽函数本质是一个回调函数, 调用的时机是信号产生之后, 调用是Qt框架来执行的
// connect中的sender和recever两个指针必须被实例化了, 否则conenct不会成功
connect(const QObject *sender, &QObject::signal,
const QObject *receiver, &QObject::method);
知道connect函数的用法之后,我们先将my_girl发送信号,m_me(m_girl和m_me 是上面加的两个成员指针)接受信号绑定在一起
在mainwindow.cpp的构造函数中添加如下语句
m_me = new Me;
m_girl = new GirlFriend;
// hungry信号是自定义的,它不能由框架去发送,因为框架压根就不知道有这个信号的存在,因此需要在特定的时机,使用者自己去发射这个信号
connect(m_girl,&GirlFriend::hungry,m_me,&Me::eat);
注意connect上面的注释
hungry信号是自定义的,它不能由框架去发送,因为框架压根就不知道有这个信号的存在,因此需要在特定的时机,使用者自己去发射这个信号
简单理解就是,你的girl要发送hungry这个信号是不能自动完成的,因为Qt框架不知道hungry这个信号,你要通过点击按钮来让girl发送信号,因此需要另外一个函数,取名为hungrySlot(),用来实现点击按钮,让girl发送信号
- 在mainwindow中定义并实现函数hungrySlot,函数定义的代码我就不放了,大家自己去定义
下面是实现代码
void MainWindow::hungrySlot()
{
// 发射自定义信号
emit m_girl->hungry();
}
注意!
这里的emit关键字也是可有可不有的 ,但是还是建议大家写,用来提醒开发人员这个函数是发射自定义信号的函数
- 现在是最关键的一步啦,将按钮与girl发射hungry信号的函数绑定,按钮被点击这个事件是可以由框架实现发送的,所以不需要我们担心
在mainwindow的构造函数中绑定,代码如下
connect(ui->hungry,&QPushButton::clicked,this,&MainWindow::hungrySlot);
这样,自定义信号槽的使用就欧克啦
接下来我们去测试一下,run一手
- 运行结果

可以看到,每次当我点击Hungry按钮,底下就会出现 “带你去吃麻辣烫”,证明我们自定义信号槽成功了
编写不易,大家要是转载啥的记得标明一下哦~
Qt自定义信号槽的使用浅析+实例的更多相关文章
- Qt 学习之路 2(5):自定义信号槽
Home / Qt 学习之路 2 / Qt 学习之路 2(5):自定义信号槽 Qt 学习之路 2(5):自定义信号槽 豆子 2012年8月24日 Qt 学习之路 2 131条评论 上一节我们详 ...
- C++11实现Qt的信号槽机制
概述 Qt的信号槽机制是Qt的核心机制,按钮点击的响应.线程间通信等都是通过信号槽来实现的,boost里也有信号槽,但和Qt提供的使用接口很不一样,本文主要是用C++11来实现一个简单的信号槽,该信号 ...
- VJGUI消息设计-兼谈MFC、QT和信号/槽机制
星期六下午4点,还在公司加班.终于写完了下周要交工的一个程序. 郁闷,今天这几个小时写了有上千行代码吧?虽然大部分都是Ctrl-C+Ctrl-V,但还是郁闷. 作为一个有10年经验的MFC程序员,郁闷 ...
- Qt学习记录--02 Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)
一 闲谈: 熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说:一切皆消息.它可以很方便实现不同窗体之间的通信,然而MFC库将很多底层的消息都屏蔽了,尽管使用户更加方便.简易地处理消息,但 ...
- 非Qt工程使用Qt的信号槽机制
非Qt工程,使用Qt的信号槽机制,蛋疼不?反正我现在就是要做这样一件蛋疼的事. 要使用Qt的信号槽机制,下面是从Qt Assist里面关于 signal & slots 的一句介绍: All ...
- QT自定义信号和槽
最近项目中使用到QT,在此记录一下QT的核心,信号与槽: QObject::connect(const QObject *sender, const char *signal, const QObje ...
- VS2008 Qt Designer 中自定义信号槽
一.Qt Designer自定义槽函数 发现:在VS2008 +Qt4.7 中打开ui文件,所用的英文QT Designer工具,没有转到槽函数的功能,不如QtCreator自带的QtDesigne ...
- 【QT学习笔记】二、信号槽和自定义信号槽
1. 信号槽 int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Qui ...
- Qt Connect 信号 槽
信号和槽机制是 QT 的核心机制 .信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方.信号和槽是 QT 自行定义的一种通信机制,它独立于标准 ...
随机推荐
- [LeetCode每日一题]88. 合并两个有序数组
[LeetCode每日一题]88. 合并两个有序数组 问题 给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组. 初始化 n ...
- 实时计算框架:Flink集群搭建与运行机制
一.Flink概述 1.基础简介 Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算.Flink被设计在所有常见的集群环境中运行,以内存执行速度和任意规模来执行计算.主要特性包 ...
- axios提交表单
后端使用@RequestBody接收jsons数据 因为后端接收json数据,所以前端也要发送json 项目的前端是使用layui的数据表单 案例方法 方法一:JSON字符串 提交的数据格式 {&qu ...
- Win10安装Ubuntu子系统(WSL)
一:设置子系统环境 关闭所有运行的程序,打开 控制面板→卸载程序→启用或关闭windows功能→勾选上适用于Linux的windows子系统 ,然后确定,完成会提示重启电脑,确定重启,等重启电脑后在操 ...
- js 实现 bind 的这五层,你在第几层?
最近在帮朋友复习 JS 相关的基础知识,遇到不会的问题,她就会来问我. 这不是很简单?三下五除二,分分钟解决. function bind(fn, obj, ...arr) { return fn.a ...
- @JsonFormat 格式化时间 时出现时间不准确问题
今天突然报个问题,简单来说说就是数据库某一字段的记录时间为 14点,然而展示到前台却是 6点 我腚眼一看,postman测试的数据也是6点 然而idea查出来的并不是6点 再仔细一瞅idea实体类的时 ...
- Solon 的过滤器 Filter 和两种拦截器 Handler、 Interceptor
在web开发中,过滤器.拦截器是经常用到的功能.它可以帮我们限制流量.验证是否登陆.记录日志以及统计执行效率等等. 今天主要交流一下 Solon 框架中的过滤器和拦截器. Solon 是什么框架? S ...
- MySQL慢日志全解析
前言: 慢日志在日常数据库运维中经常会用到,我们可以通过查看慢日志来获得效率较差的 SQL ,然后可以进行 SQL 优化.本篇文章我们一起来学习下慢日志相关知识. 1.慢日志简介 慢日志全称为慢查询日 ...
- [时间模块、random模块]
[时间模块.random模块] time模块 在Python中,通常有这几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏 ...
- Linux后台执行命令:&和nohup nohup和&后台运行,进程查看及终止
nohup和&后台运行,进程查看及终止 阅读目录 nohup和&后台运行,进程查看及终止 1.nohup 2.& 3.nohup和&的区别 &:是指在后台运 ...