QT中的信号与槽的讲解

news2025/4/24 14:57:26

文章目录

  • 信号及其特点
  • 槽及其特点
  • 代码演示
    • 标准信号与标准槽函数
      • 方式一
      • 方式二
  • 自定义信号和槽
  • connect()函数
  • 信号和槽函数存在函数重载的情况下
  • Qt的信号槽机制注意事项

信号及其特点

信号:是一种特殊的函数,又称信号函数,俗称信号,用于在对象状态发生改变时通知其他对象。信号可以包含参数,但是它们不返回任何值。
信号必须位于类定义体中,形如:void clicked(bool checked = false); 返回类型必须为void,无参数时函数名后的括号也不能省略,没有函数体。就像成员函数的声明一样,与普通成员函数的区别,除了返回值只能是void外,还有就是信号没有函数体。
在这里插入图片描述
注意: Q_SIGNALS: 或 singals: 是不能够省略的。否则编译报错。

槽及其特点

槽:是一种接收信号的函数俗称槽函数,用于响应特定事件。槽函数可以被连接到一个或多个信号,并且可以有自己的参数和返回值。
与信号的最大区别就是 槽函数有函数体,返回值类型可以是任意类型。
槽函数的位置比较自由,可以位于类定义体中,可以是全局函数,还可以是lambda表达式。
在这里插入图片描述
注意: 有种情况下是不能省略这里的 public/protected/private slots: 或 public/protected/private Q_SLOTS: 下面讲方式一时再说

QT下自动的组件类中含有大量的信号和槽函数,又被称为标准信号,和标准槽函数。

代码演示

标准信号与标准槽函数

方式一

通过 QT creator 集成的 ui design下。演示 QT中的button组件中的常见的信号与槽函数。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
每一个 .ui 文件都对应一个相应的.h头文件,mainwindow.ui 对应的 .h文件为 ui_mainwindow.h。即将.ui文件的内容翻译为C/C++语言文件。
这两个文件都不能手动修改。通过 ui designer 修改界面后,.ui文件会自动更新,而调用build命令后 ui_mainwindow.h文件会根据相应的.ui文件自动更新。
在这里插入图片描述
在这里插入图片描述
也就是我们通过界面拖动的组件都会被转化相应的一个对象。然后对这个对象的属性进行赋值等操作。
在这里插入图片描述
在这里插入图片描述

方式二

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意: 上图在MainWindow类中自动生成的槽函函数声明,前面的public/private/protected slots: 是不能省略的,否则后面 点击按钮二时,不会触发槽函数的调用。
在这里插入图片描述
在这里插入图片描述
我们发现并没有显示自动生成connect()函数进行信号和槽的关联代码。而且手动也没有添加connect()函数进行信号和槽的关联代码。
点击按钮二时 确可以调到on_pushButton_clicked函数。可以看下图:关键点 就是这行代码:QMetaObject::connectSlotsByName(MainWindow);
对应的槽函数的名称 格式必须是:on_信号发送者名称_信号名称(参数)
在这里插入图片描述
这种方式也有一个缺点(正如:QT警告Slots named on_foo_bar are error prone),就是当我们修改按钮二对象的名称后,这里的槽函数名称里的对象名称(也就是信号发送者名称)不会自动发生变化(除非再通过 Go to slot… 再生成一个新的参函数),那么编译和运行期都不会报错,但是槽函数确不会被调用。演示如下:
在这里插入图片描述
此时点击 按钮二 无任何 输出。因为 on_pushButton_clicked()不能被调到。
除非再添加一个on_pushButton2_clicked()函数并实现。
在这里插入图片描述

自定义信号和槽

myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>

class MyClass : public QObject
{
    Q_OBJECT
public:
    explicit MyClass(QObject *parent = nullptr);
    void custom_slot_0();//自定义槽函数
    
signals:
    void custom_singal();//自定义信号
    
public slots:
    void custom_slot_1();//自定义槽函数
};

void custom_slot_2();//自定义槽函数

#endif // MYCLASS_H

myclass.cpp

#include "myclass.h"
#include <QDebug>
MyClass::MyClass(QObject *parent)
    : QObject{parent}
{}

void MyClass::custom_slot_0()
{
    qDebug()<<"custom_slot_0";
}

void MyClass::custom_slot_1()
{
    qDebug()<<"custom_slot_1";
}

void custom_slot_2()
{
    qDebug()<<"custom_slot_2";
}

在主窗口类头文件中添加如下:
MyClass *myclass;
在这里插入图片描述
在主窗口类原文件中添加如下:
在这里插入图片描述
也可以写成下面这样:
在这里插入图片描述
在这里插入图片描述
在上方生成的槽函数函数体内,添加以下红框内容:
在这里插入图片描述
在这里插入图片描述

connect()函数

信号和槽关联是用QObject::connect()函数实现的,其基本格式是:

QObject::connect(sender,SIGNAL(singnal()),receiver,SLOT(slot())); //在QT4中,支持传递参数

connect()是QObject类的一个静态函数,而QObject是所有Qt类的基类,在实际调用时可以忽略前面的限定符:

connect(sender,SIGNAL(singnal()),receiver,SLOT(slot()));//在QT4中
connect(sender,SIGNAL(singnal()),receiver,SLOT(slot()));//在QT4中,支持传递参数

在QT5及以后版本支持如下格式:
连接信号和槽的connect()函数原型如下, 其中PointerToMemberFunction是一个指向函数地址的指针:

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方法,信号发出之后的处理动作
 
//  参数 signal 和 method 都是函数地址, 因此简化之后的 connect() 如下:
connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);

使用connect()进行信号槽连接的注意事项:

connect函数相对于做了信号处理动作的注册
调用conenct函数的sender对象的信号并没有产生, 因此receiver对象的method也不会被调用
method槽函数本质是一个回调函数, 调用的时机是信号产生之后, 调用是Qt框架来执行的
connect中的sender和recever两个指针必须被实例化了, 否则conenct不会成功

虽然在QT5及QT6中也支持QT4中那种方式调用,但目前不推荐使用QT4的那种connect()函数了。
但是有个问题是QT5中新增的这样connect()函数,在给信号或者槽函数传参时不能直接传递,因为它们都是传递的函数地址,所以必确确保函数无参并且函数名是唯一的,否则存在二义性,编译不过。下面说下信号和槽函数存在重载的情况下,如何使用。

信号和槽函数存在函数重载的情况下

myclass.h中添加重载函数
在这里插入图片描述
myclass.cpp文件中:
在这里插入图片描述
mainwindow.cpp:主窗口实现类中
在这里插入图片描述
关于 成员函数的地址及全局函数的地址获取方式可以看 类中成员函数及普通函数地址获取方式
在这里插入图片描述

在这里插入图片描述

Qt的信号槽机制注意事项

要使用Qt中的信号槽机制,必须继承QObject类,还需要在类的定义中的第一行写上一个宏Q_OBJECT

class MyClass: public QObject
{
    Q_OBJECT // 没有这个宏, 信号槽机制还是不能使用
    ...
}

如果没有直接继承QObject,而是继承了一些继承QObject类的其他类也可以,比如QWidget类是QObject的子类,再有个类继承QWidget也能使用信号槽的机制。还比如QMainWindow类,QMainWindow继承QWidget类。再有个类继承QMainWindow同样也能使用信号槽的机制。

还有一点是,槽函数的参数个数要小于等于信号函数的参数个数。即如果信号函数是无参的,则与其绑定的槽函数也不能写形式参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1345568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS学习--41讲 信号量

信号量的定义 是一种解决同步问题的机制&#xff0c;实现对共享资源的有序访问 信号量特点&#xff1a; 当计数值大于0&#xff0c;代表有信号量资源&#xff1b;释放信号量&#xff0c;信号量计数值1;获取则-1 队列和信号量的差异 二值信号量&#xff1a; a.相当于队列长度等…

用idea跑起十多年前的项目

一、eclipse的项目 先删掉一些eclipse的配置文件 二、在idea中导入项目 1、导入成功后&#xff0c;先【锤一下】 2、然后发现编译不通过&#xff0c;非常多的报错信息&#xff0c;逐一解决报错 &#xff08;1&#xff09;tomcat7配置报错 &#xff08;2&#xff09;先删除tom…

将本地工作空间robot_ws上传到gitee仓库

git config --global user.name "geniusChinaHN" git config --global user.email "12705243geniuschinahnuser.noreply.gitee.com" cd ~/robot_ws #git init#创建原始仓库时候用 git add . git commit -m "上传文件内容描述" #git remote add r…

【教程】Typecho Joe主题开启并修复壁纸相册不显示问题

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 Joe主题本身支持“壁纸”功能&#xff0c;其实就是相册。当时还在网上找了好久相册部署的开源项目&#xff0c;太傻了。 但是网上教程很少&#xff0c;一没说如何开启壁纸功能&#xff0c;二没说开启后为…

Java Log 学习笔记

参考文章&#xff1a; 1.Java 日志从入门到实战 2.Java日志框架的发展历史&#xff0c;你不想了解一下吗 背景 想自定义 logback 配置文件进行日志分级别记录到不同文件&#xff0c;遇到了几个问题&#xff08;使用的是 spring-boot 构建的项目&#xff0c;spring-boot 版本为…

开源可观测性平台Signoz(四)【链路监控及数据库中间件监控篇】

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 前文链接&#xff1a; ​​开源可观测性平台Signoz系列&#xff08;一&#xff09;【开篇】​​ ​​开源可观测性平台Signoz&…

记录一下imx6ull linux 5.10.9多点电容触摸屏驱动报错问题解决方法

最近再研究如何将linux 5.10.9移植到imx6ull&#xff0c;用的原子的开发板&#xff0c;在移植电容触摸屏驱动时报错gpio gpiochip0: (209c000.gpio): gpiochip_lock_as_irq: tried to flag a GPIO set as output for IRQ&#xff0c;如下图&#xff1a; 该错误的意思就是尝试将…

MongoDB Certified Associate Developer 认证考试心得

介绍 前段时间通过了 MongoDB Associate Developer 考试&#xff0c;也记下了一些心得&#xff0c;结果忘记发出来了&#xff0c;现在重新整理下。通过考试后证书是这样的: MongoDB 目前有两个认证证书 1. MongoDB Associate Developer 认证掌握使用MongoDB 来构建现代应用…

前端八股文(工程化篇)

目录 1.常用的git命令有哪些&#xff1f; 2.git rebase和git merge的区别 3.有哪些常见的Loader和Plugin&#xff1f; 4.webpack的构建流程 5.bundle,chunk,module是什么&#xff1f; 6.如何提高webpack的打包速度 7.vite比webpack快在哪里 8.说一下你对Monorepo的理解 …

EOS开发Ubuntu安装EOSIO.CDT(Install the EOSIO.CDT)

EOS开发Ubuntu安装EOSIO.CDT&#xff08;Install the EOSIO.CDT&#xff09; EOSIO.CDT介绍&#xff1a;EOSIO合约开发工具包&#xff0c;简称CDT&#xff0c;是与合约编译相关的工具集合。而且后续教程主要使用 CDT 来编译合约和生成 ABI&#xff0c;不要忽略。 刚才我们安装好…

欢迎来到Web3.0的世界:Solidity智能合约安全漏洞分析

智能合约概述 智能合约是运行在区块链网络中的一段程序&#xff0c;经由多方机构自动执行预先设定的逻辑&#xff0c;程序执行后&#xff0c;网络上的最终状态将不可改变。智能合约本质上是传统合约的数字版本&#xff0c;由去中心化的计算机网络执行&#xff0c;而不是由政府…

汽车制造厂批量使用成华制造弹簧平衡器

数年来&#xff0c;成华制造都在不断的向各行各界输出着自己的起重设备&#xff0c;与众多企业达成合作&#xff0c;不断供应优质产品。近些年&#xff0c;成华制造以其卓越的产品质量和高效的生产能力&#xff0c;成功实现了弹簧平衡器的大规模批量供应&#xff0c;为重庆数家…

【开源】基于Vue+SpringBoot的就医保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 科室档案模块2.2 医生档案模块2.3 预约挂号模块2.4 我的挂号模块 三、系统展示四、核心代码4.1 用户查询全部医生4.2 新增医生4.3 查询科室4.4 新增号源4.5 预约号源 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVue…

【Vue2+3入门到实战】(16)VUEVue路由的重定向、404、编程式导航、path路径跳转传参 详细代码示例

目录 一、Vue路由-重定向1.问题2.解决方案3.语法4.代码演示 二、Vue路由-4041.作用2.位置3.语法4.代码示例 三、Vue路由-模式设置1.问题2.语法 四、编程式导航-两种路由跳转方式1.问题2.方案3.语法4.path路径跳转语法5.代码演示 path跳转方式6.name命名路由跳转7.代码演示通过n…

工程(十七)——自己数据集跑R2live

博主创建了一个科研互助群Q&#xff1a;772356582&#xff0c;欢迎大家加入讨论。 r2live是比较早的算法&#xff0c;编译过程有很多问题&#xff0c;通过以下两个博客可以解决 编译R2LIVE问题&解决方法-CSDN博客 r2live process has died 问题解决了_required process …

优化算法3D可视化

编程实现优化算法&#xff0c;并3D可视化 1. 函数3D可视化 分别画出 和 的3D图 import numpy as np from matplotlib import pyplot as plt import torch# 画出x**2 class Op(object):def __init__(self):passdef __call__(self, inputs):return self.forward(inputs)def for…

【软考】系统集成项目管理工程师【总】

引言 本来整理这篇文章的目的是方便自己23年考试用的 效果不错 目标完成。 接下来的目标是把这篇文章 做成参加该软考 小伙伴的唯一参考资料&#xff08;有它就够了&#xff09;来持续更新。。。 这篇文章我将当作一个长周期&#xff08;以年为单位&#xff09;项目运维起来&am…

【Web】vulhub-httpd apache解析漏洞复现(1)

目录 ①CVE-2017-15715 ②apache_parsing_vulnerability ①CVE-2017-15715 贴出源码&#xff1a; <?php if(isset($_FILES[file])) {$name basename($_POST[name]);$ext pathinfo($name,PATHINFO_EXTENSION);if(in_array($ext, [php, php3, php4, php5, phtml, pht]))…

linux常见基础指令

入门常见基础指令 ls、stat、 pwd 、cd、tree、 whoami、 touch、 mkdir、 rm 、 man、 cp、mv、cat、tac、echo、>、 >>、 < 、more、 less、 head、 tail、date、 cal、 find、 which、alias、whereis、grep、zip与unzip、 tar、bc、uname、xargs... 热键Tab、…

时序分解 | Matlab实现贝叶斯变化点检测与时间序列分解

时序分解 | Matlab实现贝叶斯变化点检测与时间序列分解 目录 时序分解 | Matlab实现贝叶斯变化点检测与时间序列分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现贝叶斯变化点检测与时间序列分解 1.Matlab实现贝叶斯变化点检测与时间序列分解&#xff0c;完…