news 2026/7/9 7:24:42

【Qt初识】信号槽(二):自定义信号函数与槽函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Qt初识】信号槽(二):自定义信号函数与槽函数

大家好,我是Halcyon.平安

欢迎文末添加好友交流,共同进步!

  • 目录
    • 一、自定义槽函数
      • 1.1 背景
      • 1.2 实现
    • 二、自定义信号函数
    • 三、带参的信号函数和槽函数
      • 3.1 为什么要带参数
      • 3.2 参数规则补充说明
      • 3.3 代码演示
      • 3.4 参数个数不一致的情况

目录

一、自定义槽函数

1.1 背景

在以前的Qt版本中,槽函数必须放在public/procted/privatedslots;

slots是Qt自己扩展出来的关键字,它并不是C++的标准语法。Qt是广泛使用元变成技术(基于代码生成代码)。

qmake在构建Qt项目的时候,就会调用专门的扫描机器,识别代码中的特定关键词(如slots),然后根据特定的关键字去生成一大段相关的代码。

但是在Qt5这个新版本中我们则可以不用这样,很大的简洁了代码(毕竟谁不喜欢哪样简单用哪样呢?!),但是我还是推荐大家使用关键字,因为这样写起来是更加的规范!

1.2 实现

方式一:

我们这里通过自定义槽函数来实现通过点击按钮然后改变窗口标题来看看效果!首先我们自己新建一个项目,然后去widget.h进行声明,然后去.cpp进行函数的实现,并用connect进行连接。

publicslots:voidhandleclicked();

接下来进行槽函数的实现:

#include"widget.h"#include"ui_widget.h"#include<QPushButton>Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);QPushButton*pushbutton=newQPushButton(this);pushbutton->setText("按钮");connect(pushbutton,&QPushButton::clicked,this,&Widget::handleclicked);}Widget::~Widget(){deleteui;}voidWidget::handleclicked(){this->setWindowTitle("恭喜你,转换成功!");}

因为我使用的版本是Qt5.14的,所以如果我不在widget.hpublic slots声明这个函数也是可以运行实现的,但是为了代码的规范性所以是加上了!

方式二:

我们其实还可以用第二种方式,那句是在widget.ui中拖动按钮,然后右键选择转到槽,选择后自动生成好一个函数(定义+声明)然后我们自己去函数里编写代码即可!

因为我们的信号类型是点击按钮,所以选择clicked即可,随后会自动跳到自动生成的函数编写代码处,我们来验证一下!

我们可以看到自动生成的是使用private slots进行声明限定

我们来编写自定义槽函数代码试试!

#include"widget.h"#include"ui_widget.h"Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);}Widget::~Widget(){deleteui;}voidWidget::on_pushButton_clicked(){this->setWindowTitle("恭喜你,成功转换!")}

我们发现在第二种方法并没有通过connect连接信号和槽,但是槽函数效果的成功演示证明了着信号和槽进行了连接,那我们该如何进行理解呢?

其实在Qt中除了通过connect来连接信号槽之外,还可以通过函数名字来进行信号和槽的连接,所以我们来看看自动生成的槽函数的名称on_pushButton_clicked

  • on是固定写法
  • pushButton是Qt Designer给我们自动生成的按钮的属性objectName对应的值pushButton(关于按钮属性之前是讲过的)
  • clicked信号函数的名称

这就刚好符合connect函数要的前两个参数(信号源,信号类型),那么第三个参数就是当前on_pushButton_clicked所在的类,第四个参数就是on_pushButton_clicked这个自定义槽函数

这必须一一对应,如果哪一个参数你修改了的话,就都会运行失败!

相对于自己写代码完成信号和槽函数的连接的话我更推荐图形化创建控件,因为图形化创建控件更加的快速,能够自动连接,不需要我们自己手动去建立联系!

二、自定义信号函数

信号其实就相当于对应的是用户的操作,比如点击按钮等。我们上面讲的自定义槽函数,其实在开发中是占很大部分的,很多情况这个触发某个信号(操作)后的业务逻辑都需要我们自己去写!但是信号不一样,Qt内置的信号已经基本覆盖了这些操作!

Qt信号,本质上也是一个函数,它有两个比较特殊的点:

  • 我们只需要写函数声明,并告诉Qt这是一个“信号”,定义会在Qt的编译中自动生成。
  • 作为信号函数,返回类型必须是void,对于参数的话,有没有都可以,甚至是可重载的!

我们说需要告诉Qt这是一个信号,那么该如何告诉?对!signals,我们需要用到这个关键字,但是我们建立连接其实并不代表发射信号,那么我们如何发出信号呢!那就需要emit来进行发射(其实内置信号也是需要发射的,但是发射信号已经内置到了Qt的框架中,不需要我们自己去手动触发)!

接下来我们来自定义一个信号函数来加深理解!

signals:voidmysignal();publicslots:voidhandleMysignal();

#include"widget.h"#include"ui_widget.h"Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);connect(this,&Widget::mysignal,this,&Widget::handleMysignal);}Widget::~Widget(){deleteui;}voidWidget::handleMysignal(){this->setWindowTitle("自定义信号函数关联自定义槽函数成功!");}

有没有发现什么问题!那就是我们上面说的建立连接其实并不代表发射信号,需要emit来进行发射

{ui->setupUi(this);connect(this,&Widget::mysignal,this,&Widget::handleMysignal);emitmysignal();}

接下来我们来看看效果!

三、带参的信号函数和槽函数

信号函数带参数的时候(起到复用代码的作用),是必须要求和槽函数的参数类型必须与信号一致,但是个数可以不一致。

虽然个数可以不一致,但是信号函数的参数个数必须大于槽函数的参数个数。

那么为什么个数可以不一致呢?

  • 因为一个槽可以绑定多个信号
  • 非要要求参数个数一致的话,信号绑定槽的要求更高,没那么灵活

3.1 为什么要带参数

我们前面写的信号和槽都是不带参数的,但是大家想想,在实际开发中,光靠一个"信号来了"这种干巴巴的通知是远远不够的!比如我们窗口中有两个按钮,点击哪一个都要触发同一个槽函数去修改窗口标题,那到底要改成什么内容?这时候光靠信号本身已经不够用了,必须让信号把"具体的内容"也一起带过去!

这就是信号和槽带参数的意义——让信号在触发的同时,把数据顺带传递给槽函数,这样槽函数就能根据传过来的参数去执行不同的逻辑,从而起到复用代码的作用!

3.2 参数规则补充说明

我们把上面的规则再换个角度理解一下!信号是"发送方",槽是"接收方",发送方发送出去的东西,接收方可以选择全部接收,也可以选择只接收前面几个;但是发送方都没发出去的东西,接收方又怎么可能凭空收得到呢?所以槽函数的参数个数绝对不能超过信号函数的参数个数,这也就是为什么必须是"信号 >= 槽"!

另外参数类型也得对得上,比如信号传的是QString,槽也得用QString接收,类型不匹配的话,编译是会报错的!

3.3 代码演示

我们来自定义一个带参数的信号函数和槽函数,让信号把一个字符串带过去,槽函数接收后把它设置成窗口标题!

首先是widget.h中的声明:

signals:voidmysignal(QString text);publicslots:voidhandleMysignal(QString text);

然后是widget.cpp中的实现和连接:

#include"widget.h"#include"ui_widget.h"Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);// 建立连接:信号和槽的参数类型一致,个数也一致connect(this,&Widget::mysignal,this,&Widget::handleMysignal);// 发射信号,并把字符串作为参数一起传过去emitmysignal("带参信号成功触发了!");}Widget::~Widget(){deleteui;}voidWidget::handleMysignal(QString text){this->setWindowTitle(text);}

运行后我们就能看到窗口标题被成功修改了!这说明信号在发射的时候,确实把字符串 text 这个参数顺带传给了槽函数,槽函数接收到之后用它来设置窗口标题!

3.4 参数个数不一致的情况

上面是参数个数一致的情况,那么我们前面说的"个数可以不一致"又是怎样的呢?我们把槽函数的参数省略掉试试!

signals:voidmysignal(QString text);publicslots:voidhandleMysignal();// 槽函数不接收参数

这样同样是合法的!信号带了参数,槽函数可以"选择性失明",只接收信号触发的这个时机,不接收信号带的数据,这就是 Qt 信号槽给我们提供的灵活之处!

但是要注意:如果反过来,信号没有参数,而槽函数却有参数,那就是不行的了!因为槽函数需要的参数,信号根本就没传过来,这就违背了我们前面讲的"信号 >= 槽"的规则,运行时也就不会得到我们想要的结果!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/9 7:24:28

微信群消息自动转发完整指南:3步实现跨群信息同步

微信群消息自动转发完整指南&#xff1a;3步实现跨群信息同步 【免费下载链接】wechat-forwarding 在微信群之间转发消息 项目地址: https://gitcode.com/gh_mirrors/we/wechat-forwarding 还在为微信群消息管理而烦恼吗&#xff1f;每天需要在不同群组间手动转发消息&a…

作者头像 李华
网站建设 2026/7/9 7:20:37

校招季消息发不完,如何告别重复邀约内耗

一、人工逐条邀约&#xff0c;HR的无效内耗来源 春招、暑期实习、秋招等集中招聘的阶段&#xff0c;几乎所有HR都会陷入重复性工作的循环&#xff1a;同步开放多个实习岗位后&#xff0c;后台积累了大量意向学生&#xff0c;需要逐个编辑消息、单独发送面试邀约、确认到场时间…

作者头像 李华
网站建设 2026/7/9 7:19:58

多个 AI 怎么「开会不抢话」?AutoGen Group Chat 一文讲透

作者&#xff1a;AI 技术笔记 参考&#xff1a;AutoGen 官方文档 Group Chat 阅读时间&#xff1a;约 6 分钟 开头说人话 你有没有想过&#xff1a;一个 AI 写文案&#xff0c;一个 AI 画图&#xff0c;一个 AI 当编辑——它们怎么配合&#xff0c;才不会乱成一锅粥&#xff…

作者头像 李华
网站建设 2026/7/9 7:17:14

MambaDFuse 多模态图像融合实战:RTX 4090 双卡训练,8大指标超越SOTA

MambaDFuse多模态图像融合实战&#xff1a;RTX 4090双卡训练与性能突破指南1. 前沿技术解析&#xff1a;为什么选择Mamba架构&#xff1f;在计算机视觉领域&#xff0c;多模态图像融合&#xff08;MMIF&#xff09;一直是提升下游任务性能的关键预处理步骤。传统方法面临三大核…

作者头像 李华
网站建设 2026/7/9 7:14:50

计算机毕业设计之旅游资源及线路管理系统

随着当今社会的发展&#xff0c;时代的进步&#xff0c;各行各业也在发生着变化&#xff0c;本系旅游资源及线路这一方面&#xff0c;利用网站旅游资源及线路已经逐步进入人们的生活。传统的旅游资源及线路管理&#xff0c;网络以及计算机为解决当前的问题提供了新的方向新的可…

作者头像 李华