Qt自定义信号和槽函数

2023-05-16

文章目录

    • 自定义信号函数
    • 自定义槽函数
    • 自定义信号和槽的完整实例

已剪辑自: http://c.biancheng.net/view/vip_9662.html

实际开发中,如果仅使用 Qt 提供的信号函数和槽函数,会经常遇到信号函数的参数类型和个数无法满足实际需求、信号函数和槽函数的参数类型不匹配等问题。解决此类问题,最简单有效的方式就是:自定义场景需要的信号函数和槽函数。

自定义信号函数

信号函数指的是符合以下条件的函数:

  • 定义在某个类中,该类直接或间接继承自 QObject 类;
  • 用 signals 关键字修饰;
  • 函数只需要声明,不需要定义(实现);
  • 函数的返回值类型为 void,参数的类型和个数不限。

举个简单的例子:

class MyWidget:public QWidget{
    //Q_OBJECT 是一个宏,添加它才能正常使用 Qt 的信号和槽机制
    Q_OBJECT
//修饰信号函数的关键字
signals:
    //自定义的信号函数
    void MySignal(QString message);
};

我们自定义了一个继承自 QWidget 的 MyWidget 类,QWidget 是 QObject 的子类,所以 MyWidget 间接继承自 QObject 类。MyWidget 类中自定义了名为 MySignal 的信号函数(可以简称 MySignal 信号),它用 signals 关键字修饰,没有返回值,也没有定义(实现),仅有 1 个参数。

对于 MySignal() 信号函数,程序中不会直接调用它,而是借助 connect() 连接某个槽函数,实现的语法格式是:

MyWidget myWidget;
QObject::connect(&myWidget,&MyWidget::MySignal,信号接收者,槽函数);

一旦确定了信号接收者和槽函数,当 MySignal 信号发出后,与之相连的槽函数就会执行。那么,程序中如何发出 MySignal 信号呢?

对于 Qt 提供给我们的信号函数,其底层已经设置好了信号发出的时机,例如按下鼠标时、点击 Enter 回车键时等等。对于自定义的信号,我们需要自己指定信号发出的时机,这就需要用到 emit 关键字。emit 中文意思为“发出、射出”,是 Qt 在 C++ 基础上扩展的一个关键字,专门用来发射信号。

以定义好的 MySignal 信号为例,修改 MyWidget 类为:

class MyWidget:public QWidget{
    //Q_OBJECT 是一个宏,添加它才能正常使用 Qt 的信号和槽机制
    Q_OBJECT
//自定义信号函数
signals:
    void MySignal(QString mess);
public:
    void emitSignal(){
        emit MySignal(message);
    }
private:
    QString message;
};

我们为 MyWidget 类新增了一个 emitSignal() 方法和一个 message 属性,emitSignal() 方法中的emit MySignal(message);语句就表示发射 MySignal 信号。当程序中执行 emitSingal() 函数时,就会发出 MySignal 信号,message 属性的值也会随信号一同发出,对应的槽函数可以接收到 message 的值。

对于每一个自定义的信号函数,程序中都应该提供发射该信号的方法(函数),而且这样的方法(函数)可以有多个。

自定义槽函数

Qt5 中,槽函数既可以是普通的全局函数、也可以是类的成员函数、静态成员函数、友元函数、虚函数,还可以用 lambda 表达式表示。

和信号函数不同,槽函数必须手动定义(实现)。槽函数可以在程序中直接调用,但主要用来响应某个信号。自定义一个槽函数时,需要注意以下几点:

  • 槽函数的返回值必须和信号函数相同,由于信号函数的返回值一定是 void,所以槽函数的返回值也必须为 void;
  • 对于带参的信号函数,槽函数可以选择接收所有参数,则参数的类型、顺序、个数都必须与信号函数相同;也可以选择接收前几个参数,这些参数的类型、顺序都必须与信号函数相同;还可以选择不接受任何参数。
  • 槽函数的参数个数只能比信号函数少,不能比信号函数多;
  • 槽函数的参数不能有默认值。

举个例子,自定义响应 MySignal 信号的槽函数:

class MyWidget:public QWidget{
    //Q_OBJECT 是一个宏,添加它才能正常使用 Qt 的信号和槽机制
    Q_OBJECT
signals:
    void MySignal(QString mess1,QString mess2);
public:
    void emitSignal(){
        emit MySignal(message1,message2);
    }
    //类的成员函数
    void recSlot1(QString mess){
        qDebug() << "执行 recSlot1() 成员函数,输出" << mess;
    }
//指明定义的是槽函数
public slots:
    void recSlot2(QString mess1,QString mess2){
        qDebug() << "执行 recSlot2() 槽函数,输出"<< mess1 << " " << mess2;
    }
public:
    QString message1;
    QString message2;
};
//全局函数
void recSlot3(){
    qDebug() << "执行 recSlot3() 全局函数";
}

程序中,重点关注 recSlot1()、recSlot2()、recSlot3() 这 3 个函数:

  • recSlot1() 是 MyWidget 类内部的 public 成员函数,可以当做槽函数使用;
  • recSlot2() 位于 MyWidget 类的内部,修饰它的关键字是 public slots。slots 和 emit 一样,是 Qt 扩展的一个关键字,专门用来修饰槽函数。也就是说,recSlot2() 是 MyWidget 类中的槽函数。
  • recSlot3() 是全局函数,可以当做槽函数使用。

slots 关键字可以和 public、protected、private 搭配使用,它们的区别是:

  • public slots:该关键字修饰的槽函数,既可以在当前类及其子类的成员函数中调用,也可以在类外部的其它函数(比如 main() 函数)中调用;
  • protected slots:该关键字修饰的槽函数,仅允许在当前类及其子类的成员函数内调用,不能在类外部的其它函数内调用;
  • private slots:该关键字修饰的槽函数,只允许在当前类的成员函数内调用,不能在子类中调用,也不能在类外部的其它函数内调用。

通常情况下,槽函数使用 public slots 修饰。

很多读者会问,既然 public 修饰的成员函数可以当做槽函数,为什么还要提供 slots 关键字呢?笔者认为,“兼容旧的 Qt 版本”是其中的一个原因。Qt4 中的槽函数只能是 slots 修饰的类成员函数,Qt5 中取消了这一限制,但考虑到要兼容旧的 Qt 版本,Qt5 保留了旧版本中 connect() 函数的语法格式,也保留了 slots 关键字。

调用 connect() 函数,将 MySignal() 信号函数分别连接 recSlot1()、recSlot2()、recSlot3() 三个槽函数,实现代码为:

//类的成员函数作为槽函数
QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot1);
//信号函数和槽函数相连接
QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot2);
//全局函数作为槽函数
QObject::connect(&mywidget,&MyWidget::MySignal,&recSlot3);

自定义信号和槽的完整实例

//main.cpp
#include <QApplication>
#include <QWidget>
#include <QDebug>
class MyWidget:public QWidget{
    //Q_OBJECT 是一个宏,添加它才能正常使用 Qt 的信号和槽机制
    Q_OBJECT
//信号函数
signals:
    void MySignal(QString mess1,QString mess2);
public:
    //发射信号的函数
    void emitSignal(){
        emit MySignal(message1,message2);
    }
    //普通类成员函数
    void recSlot1(QString mess){
        qDebug() << "执行 recSlot1() 成员函数,输出" << mess;
    }
//槽函数
public slots:
    void recSlot2(QString mess1,QString mess2){
        qDebug() << "执行 recSlot2() 槽函数,输出"<< mess1 << " " << mess2;
    }
public:
    QString message1;
    QString message2;
};
//全局函数
void recSlot3(){
    qDebug() << "执行 recSlot3() 全局函数";
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //创建主窗口
    MyWidget mywidget;
    mywidget.message1 = "C语言中文网";
    mywidget.message2 = "http://c.biancheng.net";
    //类的成员函数作为槽函数
    QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot1);
    //信号函数和槽函数相连接
    QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot2);
    //全局函数作为槽函数
    QObject::connect(&mywidget,&MyWidget::MySignal,&recSlot3);
    mywidget.show();
    //发射 Signal 信号
    mywidget.emitSignal();
    return a.exec();
}
//MyWidget类的定义应该放到 .h 文件中,本例中将其写到 main.cpp 中,程序最后需要添加 #include "当前源文件名.moc" 语句,否则无法通过编译。
#include "main.moc"

执行程序,会弹出一个 myWidget 空白窗口,同时输出以下信息:

执行 recSlot1() 成员函数,输出 “C语言中文网”
执行 recSlot2() 槽函数,输出 “C语言中文网” “http://c.biancheng.net”
执行 recSlot3() 全局函数

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt自定义信号和槽函数 的相关文章

  • 如何画架构图?

    平时做过一些系统设计 xff0c 也写过一些系统分析文章 xff0c 从组件 关系 交互等方面提供一些建议 xff0c 并用我之前写文章画的一些图举些例子 构成系统的组件通过形状 颜色 名称来逼近其概念 LevelDB 主要构件如上面 Le
  • 主定理的证明及应用举例

    主定理 主定理最早出现在 算法导论 中 xff0c 提供了分治方法带来的递归表达式的渐近复杂度分析 规模为n的问题通过分治 xff0c 得到a个规模为n b的问题 xff0c 每次递归带来的额外计算为c n d T n lt 61 aT n
  • 程序员怎样才能写出一篇好的博客或者技术文章?

    文章目录 来分享下鹅厂多位技术同学关于如何写好技术文章的经验 1 为什么要写文章 1 1 对作者的好处 1 1 1 复盘学习成果 xff0c 巩固知识理解 1 1 2 提升思考能力 1 1 3 传播技术知识 xff0c 积累技术资产 1 1
  • 数字孪生技术有没有真正的实用价值?

    作为一个数字孪生领域的技术公司负责人 xff0c 我尽可能用比较直白的话来描述一下我对数字孪生行业以及数字孪生价值的理解 纵观数字孪生相关的公司 xff0c 主要有两个流派 xff0c 一派是具有互联网基因的数字孪生创业公司 xff0c 一
  • 你在编程过程中养成了哪些好习惯?

    写工作日志 我一直有大量写笔记的习惯 编程的时候 xff0c 也经常遇到一些麻烦的问题 xff0c 思路转瞬即逝 xff0c 于是把所有这些思路记录下来 xff0c 会在以后的搜索中成为重要的灵感来源 我的工作日志里通常以项目为单位 xff
  • 如何让 PPT 中的表格更美观?

    这个不难 xff0c 不信你看 做PPT表格 xff0c 千万不要直接把Excel截个图粘贴到PPT里 或者网上找到相应的表格图片 xff0c 也直接粘贴到PPT中 这样做的PPT表格肯定不好看呀 今天和大家分享几个表格美化的小技巧 xff
  • 这次把怎么做好一个PPT讲清-演讲篇

    商务演讲与汇报 一 目标 xff1a 演讲必须有清晰的目标 演讲 xff1a 影响他人发生积极的 改变 注意 xff0c 目标就要设定的影响听众在听完你的演讲后发生积极的改变 xff1b 例 xff1a 5月初向领导做月度工作汇报 让领导在
  • 这次把怎么做好一个PPT讲清-动画篇

    干货预警 xff01 作为一位PPT发烧友看过诸多PPT案例 xff0c 分享几个高大上的动画效果 文末有福利 xff01 废话不多说 xff0c 直接上重点 xff0c 本文主要讲八个动画技巧 xff0c 我们来看先目录 xff1a 收藏
  • 重新认知发明,全网保姆级入门说明

    已剪辑自 https mp weixin qq com s IDQXYXpWQlaW1NyX36H2vQ 关注 林外的日课 公众号 xff1a 每日思考 xff0c 每周更新 发明 xff0c 是指对产品 方法或者其改进所提出的新的技术方案
  • 软件测试需要掌握哪些技术?

    文章目录 1 黑盒测试 白盒测试 灰盒测试1 1 黑盒测试1 2 白盒测试1 3 灰盒测试 2 自顶向下集成和自底向上集成各自的优缺点 2 1 自顶向下集成2 2 自底向上集成 3 按照开发阶段划分 xff0c 软件测试可以分为哪几个流程
  • 画时序图的四个好用的工具~

    已剪辑自 https mp weixin qq com s xvCOLaGARp15vCRq6w8h2Q 分享几个画时序图的软件 xff0c 一些通信协议 xff0c 如I2C SPI UART MIPI等 xff0c 都会涉及到时序 Ti
  • Google软件工程:什么是软件工程

    文章目录 编程 软件工程软件工程的3个特性时间与变化海勒姆定律 xff08 Hyrum s Law xff09 目标不是 没有变化 规模和效率左移思维 权衡和成本最后 已剪辑自 https mp weixin qq com s GhYfH3
  • 多普勒失真信号重采样的Matlab仿真分析

    多普勒失真信号重采样的Matlab仿真分析 应用场景 水声通信指的是使用声信号在水中传输数据 相对而言 xff0c 电磁信号在水中吸收严重衰减过快 xff0c 光信号受水中悬浮颗粒的影响 xff0c 也无法完成远距离传输 这两种信号的传播距
  • 嵌入式为何钟爱SourceInsight,主要因为这个功能~

    已剪辑自 https mp weixin qq com s F gafwbZswpnY8EaCz8HxQ 不管是玩单片机还是嵌入式linux xff0c 只要是与硬件结合比较紧密的部分目前基本上还是C语言 xff0c 当然了 xff0c 不
  • 华科师兄最近的六条感悟

    已剪辑自 https mp weixin qq com s P6vz2zDTnCNli0GdyKX98Q 孤独之前是迷茫 孤独之后便是成长 曾经我是一个无法承受孤独的人 xff0c 无法和自己独处 xff0c 喜欢喧嚣的感觉 慢慢我发现这种
  • 一个优秀的程序员应该养成哪些好的习惯?

    文章目录 一 写代码前先想好思路 xff0c 先规划框架 xff0c 再到局部实现二 注重代码风格三 注重代码执行效率四 掌握一些编码原则五 解决问题时 xff0c 对于原理性的问题 xff0c 不要面向搜索引擎编程 六 注重基础知识的学习
  • 嵌入式开发中的防御性C语言编程

    嵌入式产品的可靠性自然与硬件密不可分 xff0c 但在硬件确定 并且没有第三方测试的前提下 xff0c 使用防御性编程思想写出的代码 xff0c 往往具有更高的稳定性 防御性编程首先需要认清C语言的种种缺陷和陷阱 xff0c C语言对于运行
  • PPT 最后一页写什么结束语既得体又能瞬间提升格调?

    谢邀 xff01 我只分享一个现下最流行的方法 xff0c 绝对让尾页逼格满满 xff01 罗永浩雷军都在用的 金句法 提到这份方法 xff0c 你可能会觉得很陌生 xff0c 但你一定见过这样的页面 xff1a 这样的页面还有很多 xff
  • Qt控件和事件

    文章目录 什么是 Qt 控件什么是Qt事件总结 已剪辑自 http c biancheng net view vip 9651 html Qt 是一个著名的 GUI 框架 xff0c 用来开发和用户交互的图形界面 作为 GUI 框架 xff

随机推荐

  • Qt信号和槽机制详解

    文章目录 信号和槽connect 函数实现信号和槽实例演示信号和槽机制 已剪辑自 http c biancheng net view vip 9652 html 信号和槽是 Qt 特有的消息传输机制 xff0c 它能将相互独立的控件关联起来
  • Qt QLabel文本框的使用

    文章目录 QLabel文本框的使用QLabel文本框的信号和槽实例演示QLabel文本框的用法 已剪辑自 http c biancheng net view vip 9653 html QLabel 是 Qt 帮我们写好的一个控件类 xff
  • Qt QPushButton按钮用法详解

    文章目录 QPushButton按钮的创建QPushButton按钮的使用QPushButton按钮的信号和槽实例演示QPushButton按钮用法 已剪辑自 http c biancheng net view vip 9654 html
  • Qt QLineEdit单行输入框用法详解

    已剪辑自 http c biancheng net view vip 9655 html QLineEdit 是 Qt 提供的一个控件类 xff0c 它直接继承自 QWdiget 类 xff0c 专门用来创建单行输入框 xff0c 如下图所
  • 使用python开发json、csv数据格式转换工具

    使用python开发json csv数据格式转换工具 json和xml是业界常用的数据格式 xff0c 而游戏行业经常使用csv配表 xff0c 包括本地化文本和数值 本文介绍csv和json序列化 逆序列化相关的python库 xff0c
  • 【学习QT必备的C++基础】C++类和对象

    文章目录 C 43 43 类的定义和对象的创建详解类的定义创建对象访问类的成员使用对象 指针 http c biancheng net c 80 总结 C 43 43 类的成员变量和成员函数详解在类体中和类体外定义成员函数的区别 C 43
  • 【学习QT必备的C++基础】C++引用精讲,C++ &用法全面剖析

    文章目录 C 43 43 引用10分钟入门教程C 43 43 引用作为函数参数C 43 43 引用作为函数返回值 C 43 43 引用在本质上是什么 xff0c 它和指针到底有什么区别 xff1f 引用和指针的其他区别 C 43 43 引用
  • 【学习QT必备的C++基础】C++继承、派生与多态

    文章目录 C 43 43 继承和派生简明教程C 43 43 三种继承方式public protected private 修饰类的成员public protected private 指定继承方式改变访问权限 C 43 43 继承时的名字遮
  • QT中组件/控件类的关系

    一 常见类继承关系 二 窗口类继承关系 Qt中窗口类的继承关系 说明 xff1a QWidge继承自QObject和QPaintDevice类 QObject是支持QT对象模型的基类 Qt Object Model QPaintDevice
  • Qt QListWidget列表框用法详解

    文章目录 QListWidget列表框的创建QListWidgetItem列表项 QListWidget列表框的使用QListWidget列表框的信号和槽实例演示QListWidget列表框的用法 已剪辑自 http c biancheng
  • Qt QTreeWidget树形控件用法详解

    文章目录 QTreeWidget控件的创建QTreeWidget QTreeView的关系和区别QTreeWidgetItem类 QTreeWidget的实际应用1 添加结点2 给结点添加图标3 给结点添加复选框4 多列树形控件5 QTre
  • Qt QMessageBox用法详解

    文章目录 通用的QMessageBox消息框1 information消息对话框2 critical消息对话框3 question消息对话框4 warning消息对话框5 about和aboutQt对话框 自定义QMessageBox对话框
  • Qt pro文件详解

    文章目录 pro文件中的配置信息QT配置项 已剪辑自 http c biancheng net view vip 9661 html 默认情况下 xff0c 每个 Qt 项目都包含一个后缀名为 pro 名称和项目名相同的文件 xff0c 我
  • mac上用qt创建应用 运行后为什么不显示窗体

    mac上安装了qt xff0c 新建mainwindow窗体应用 xff0c 运行后在程序坞出现了一个图标 xff0c 但是无法显示窗体 解决方法 xff1a 软件配置的SDK远大于电脑配置的SDK xff0c 下个低的版就好了
  • Qt Designer基础控件介绍

    已剪辑自 https blog csdn net qq 37631516 article details 104786627 1 布局类 xff08 4种 xff09 2 固定弹簧类 2种 xff08 不随布局变化 xff09 3 按钮类
  • python开发环境管理:pip和virtualenv

    python开发环境管理 xff1a pip和virtualenv 不同的python软件需要不同的开发环境 xff0c 互相之间甚至可能有冲突 xff0c 怎么处理 xff1f 使用pip virtualenv和virtualenvwra
  • Qt QFile文件操作详解

    文章目录 QFile文件操作QFile 43 QTextStreamQFile 43 QDataStream 文件操作是非常重要的 xff0c 是数据持久化的方法 通过文件操作 xff0c 我们可以把在软件中设置的数据保存起来 已剪辑自 h
  • Qt布局管理详解(5种布局控件)

    文章目录 QVBoxLayout垂直布局QHBoxLayout水平布局QGridLayout网格布局QFormLayout表单布局QStackedLayout分组布局 已剪辑自 http c biancheng net view vip 9
  • 基于优先级的时间片轮转调度算法(C语言实现)

    已剪辑自 http www demodashi com demo 15341 html 基于优先级的时间片轮转调度算法 1 PCB结构 xff08 Block xff09 由此定义如下结构体 xff1a span class token k
  • Qt自定义信号和槽函数

    文章目录 自定义信号函数自定义槽函数自定义信号和槽的完整实例 已剪辑自 http c biancheng net view vip 9662 html 实际开发中 xff0c 如果仅使用 Qt 提供的信号函数和槽函数 xff0c 会经常遇到