QT中的信号与槽的讲解

文章目录

  • 信号及其特点
  • 槽及其特点
  • 代码演示
    • 标准信号与标准槽函数
      • 方式一
      • 方式二
  • 自定义信号和槽
  • 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.rhkb.cn/news/227701.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年新一代开发者工具 Vue ,正式开源!

以下文章来源于前端充电宝 &#xff0c;作者CUGGZ 近日&#xff0c;Vue 新一代开发者工具&#xff08;DevTools&#xff09;正式开源&#xff01;Vue DevTools 是一个旨在增强 Vue 开发人员体验的工具&#xff0c;它提供了一些功能来帮助开发者更好地了解 Vue 应用。下面就来看…

第九部分 图论

目录 例 相关概念 握手定理 例1 图的度数列 例 无向图的连通性 无向图的连通度 例2 例3 有向图D如图所示&#xff0c;求 A, A2, A3, A4&#xff0c;并回答诸问题&#xff1a; 中间有几章这里没有写&#xff0c;感兴趣可以自己去学&#xff0c;组合数学跟高中差不多&#xff0c…

记录汇川:MODBUS TCP-梯形图

H5U的MODBUS通信不需要编写程序&#xff0c;通过组态MODBUS通信配置表&#xff0c;实现数据通信。 Modbus-TCP 主站即Modbus-TCP客户端&#xff0c;通过Modbus-TCP配置&#xff0c;可最多支持同时与31个 Modbus-TCP服务器&#xff08;从站&#xff09;进行通讯。 …

【51单片机系列】DS18B20温度传感器模块

本文是关于温度传感器的相关内容。 文章目录 一、 DS18B20数字温度传感器介绍1.1、 DS18B20温度传感器的特点1.2、DA18B20内部结构1.3、 DS18B20的温度转换规则1.4、 DS18B20的ROM指令表1.6、 计算温度1.7、 读写时序 二、DS18B20使用示例 一、 DS18B20数字温度传感器介绍 DS1…

CloneNotSupportedException的解决方案 + Object的clone方法分析

CloneNotSupportedException的解决方案 引入问题&#xff1a; 在一次测试clone方法时&#xff0c;D类Override了Object类的clone方法 public class D {private Integer A1;private Integer A2;public D() {}public D(Integer a1, Integer a2 {A1 a1;A2 a2;}Overrideprotec…

Vlan的封装模式和端口讲解(Access、Trunk、Hypbrid端口)

目录 Vlan的封装模式 ISL协议 802.1Q协议 二层接口类型 Access接口 Trunk接口 Hybrid接口 不同Vlan之间的通信 Vlan的作用&#xff08;Vlan工作于OSI参考模型的第二层&#xff09; Vlan&#xff08;Virtual Local Area Network&#xff09;虚拟局域网&#xff0c;将一个…

公司电脑文件加密系统——防止内部核心文件数据 | 资料外泄,自动智能透明加密保护

一套从源头上保障企业电脑数据安全和电脑使用安全的加密软件。天锐绿盾加密软件包含了表格数据加密、图纸加密、文档文件加密、内网文件加密流转、密级管控、电脑离线管理、文件外发管理、灵活的审批流程、工作模式切换、服务器白名单等功能。天锐绿盾加密系统全面覆盖Mac、Win…

WeNet语音识别分词制作词云图

在线体验 ,点击识别语音需要等待一会&#xff0c;文件太大缓存会报错 介绍 本篇博客将介绍如何使用 Streamlit、jieba、wenet 和其他 Python 库&#xff0c;结合语音识别&#xff08;WeNet&#xff09;和词云生成&#xff0c;构建一个功能丰富的应用程序。我们将深入了解代码…

用CSS中的动画效果做一个转动的表

<!DOCTYPE html> <html lang"en"><head><meta charset"utf-8"><title></title><style>*{margin:0;padding:0;} /*制作表的样式*/.clock{width: 500px;height: 500px;margin:0 auto;margin-top:100px;border-rad…

力扣:62. 不同路径(动态规划,附python二维数组的定义)

题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&…

使用vmware,在ubuntu18.04中使用笔记本的摄像头

步骤1&#xff1a;在windows中检查相机状态 win10系统中&#xff0c;在左下的搜索栏&#xff0c;搜索“相机”&#xff0c;点击进入即可打开相机&#xff0c;并正常显示图像。 注意&#xff1a;如果相机连接到了虚拟机&#xff0c;则不能显示正常。 步骤2&#xff1a;在ubuntu…

百度沧海文件存储CFS推出新一代Namespace架构

随着移动互联网、物联网、AI 计算等技术和市场的迅速发展&#xff0c;数据规模指数级膨胀&#xff0c;对于分布式文件系统作为大规模数据场景的存储底座提出了更高的要求。已有分布式文件系统解决方案存在着短板&#xff0c;只能适应有限的场景&#xff1a; >> 新型分布式…

Vue.js学习笔记(1)——Visual Studio Code搭建Vue.js框架

1 安装Node.js 1、下载安装包&#xff1a;进入官网&#xff08;https://nodejs.org/en&#xff09;&#xff0c;下载左侧的稳定版。 2、选择安装位置&#xff0c;不用勾选自动安装必要工具。 其他都默认Next。 配置环境&#xff0c;具体参考本文章&#xff1a; https://blo…

性能测试-jmeter:安装 / 基础使用

一、理解jmeter 官网-Apache JMeter-Apache JMeter™ JMeter是一款开源的性能测试工具&#xff0c;主要用于模拟大量用户并发访问目标服务器&#xff0c;以评估服务器的性能和稳定性。 JMeter可以执行以下任务序号用途描述1性能测试通过模拟多个用户在同一时间对服务器进行请…

Markdown之EBNF语法介绍(二十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

2023 年中国金融级分布式数据库市场报告:TiDB 位列领导者梯队,创新能力与增长指数表现突出

近日&#xff0c;沙利文联合头豹研究院发布了中国数据库系列报告之《2023 年中国金融级分布式数据库市场报告》。 报告认为&#xff0c;金融行业对于分布式数据库信任度与认可度正在逐步提高&#xff0c;中国金融级分布式数据库市场正处于成熟落地的高增长阶段&#xff0c;行业…

Ubuntu安装K8S的dashboard(管理页面)

原文网址&#xff1a;Ubuntu安装k8s的dashboard&#xff08;管理页面&#xff09;-CSDN博客 简介 本文介绍Ubuntu安装k8s的dashboard&#xff08;管理页面&#xff09;的方法。 Dashboard的作用有&#xff1a;便捷操作、监控、分析、概览。 相关网址 官网地址&#xff1a;…

Android Studio如何创建尺寸大小及API通用的模拟器

目录 前言 一、操作步骤 二、总结 三、更多资源 前言 在开发移动应用程序的过程中&#xff0c;使用模拟器进行测试是一种常见和方便的方式。Android Studio是一款功能强大的集成开发环境&#xff0c;它提供了创建和管理模拟器的功能。在本文中&#xff0c;我们将介绍如何创…

前端三件套html/css/js的基本认识以及示例程序

简介 本文简要讲解了html,css,js.主要是让大家简要了解网络知识 因为实际开发中很少直接写html&css,所以不必过多纠结,了解一下架构就好 希望深度学习可以参考MDN和w3school HTML 基础 HTML (Hyper Text Markup Language) 不是一门编程语言,而是一种用来告知浏览器如…

【Java】log4j和slf4j区别

log4j&#xff1a;Apache Software Foundation 开源 slf4j&#xff1a;不支持日志滚动等高级功能 在开源库或内部库中使用 SLF4J&#xff0c;将使其独立于任何特定的日志记录实现&#xff0c;这意味着无需为多个库管理多个日志记录配置&#xff0c;您的客户端将会很需要这一点…