QT —— 信号和槽(槽函数)
QT —— 信号和槽
- 信号和槽
- 信号(Signal)
- 槽(Slot)
- 声明方式
- 工作原理
- 连接方式
- 1. 传统连接方式(Qt4风格)
- 2. 新式连接方式(Qt5风格)
- 区分槽函数和信号
- 通过QtCreator生成信号槽代码
- 自动生成槽函数
- 显式连接的优势
- 命名约定自动连接的局限性
- 最佳实践建议
- 结论
我们之前对QT,有了一个大致的了解,如果还有对QT这个概念还不清楚的小伙伴可以点击这里:
https://blog.csdn.net/qq_67693066/category_12625974.html
今天我们来了解一下QT当中的信号和槽,这个主要就是和connect函数有关系:
信号和槽
其实我们之前已经简单使用过了信号和槽的功能,就是我们用其他方式实现HelloWorld的时候:
connect函数是最好的例子,这里的connect函数的意思是:mybutton会发出&QPushButton中的clicked信号,然后这个信号会被this(也就是Widget接收),接收之后,处理方法为handler:
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);mybutton = new QPushButton(this); //创建一个按钮mybutton->move(200,300); //修改按钮位置mybutton->setText("这是一个按钮"); connect(mybutton,&QPushButton::clicked,this,&Widget::handler);
}void Widget::handler()
{if(mybutton->text() == "这是一个按钮"){mybutton->setText("你点击了按钮");}else if(mybutton->text() == "你点击了按钮"){mybutton->setText("这是一个按钮");}
}Widget::~Widget()
{delete ui;
}
其实可以把connect函数里面的参数可以分类一下:
这样的话我们就一目了然了,下面我们来介绍一下信号和槽的概念:
信号和槽(Signals & Slots)是Qt框架的核心特性,用于对象间的通信。它是一种强大的观察者模式实现,比传统的回调函数更灵活、更安全。
信号(Signal)
- 由对象在特定事件发生时发出的通知
- 只需声明,不需要实现(由moc自动生成)
- 可以带有参数,用于传递数据
槽(Slot)
- 响应特定信号的函数
- 需要实现,可以是普通成员函数
- 可以接收信号传递的参数
声明方式
class MyClass : public QObject
{Q_OBJECT // 必须包含这个宏public:explicit MyClass(QObject *parent = nullptr);signals: // 信号声明区void valueChanged(int newValue);void operationCompleted();public slots: // 槽函数声明区void setValue(int value);void doSomething();private slots:void internalHandler();
};
工作原理
- 当信号被发射(emit)时,所有连接到该信号的槽函数都会被调用
- 一个信号可以连接多个槽
- 多个信号可以连接到一个槽
- 信号可以连接到另一个信号(形成信号链)
连接方式
1. 传统连接方式(Qt4风格)
connect(sender, SIGNAL(valueChanged(int)), receiver, SLOT(setValue(int)));
2. 新式连接方式(Qt5风格)
connect(sender, &SenderClass::valueChanged, receiver, &ReceiverClass::setValue);
区分槽函数和信号
我们在写代码的时候要注意槽函数和信号,槽函数的标识像一把梳子,而信号则有像WiFi一样的符号:
通过QtCreator生成信号槽代码
如果我们创建按钮是在ui界面上创建的,还有一种方式可以帮助我们隐式连接,我们进入ui,创建一个按钮,右击转到槽:
选择对应的信号:
点击OK,会自动生成一个函数:
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->pushButton->setText("这是一个按钮");
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{if(ui->pushButton->text() == "这是一个按钮"){ui->pushButton->setText("你点击了按钮");}else if(ui->pushButton->text() == "你点击了按钮"){ui->pushButton->setText("这是一个按钮");}
}
这样和显示用connect是一样的效果:
自动生成槽函数
⾃动⽣成槽函数的名称有⼀定的规则。槽函数的命名规则为:on_XXX_SSS,其中:
1、以"on"开头,中间使用下划线连接起来;
2、"XXX"表示的是对象名(控件的 objectName 属性)。
3、"SSS"表示的是对应的信号。
如:"on_pushButton_clicked()",pushButton代表的是对象名,clicked是对应的信号。
在Qt开发中,信号和槽的连接方式主要有两种风格:基于命名约定的自动连接和显式的connect
调用。虽然Qt支持通过特定命名规则自动连接信号槽,但我更推荐开发者使用显式connect
的方式,原因如下:
显式连接的优势
-
代码可读性更强
- 通过
connect
语句可以一目了然地看到对象间的通信关系 - 避免隐藏在命名规则中的"魔法连接",降低理解成本
- 通过
-
编译时检查(Qt5新语法)
- 使用新式语法
connect(sender, &Sender::signal, receiver, &Receiver::slot)
时 - 编译器会检查信号和槽的签名是否匹配,提前发现错误
- 使用新式语法
-
减少隐式错误
- 避免因拼写错误导致的连接失效
- 防止因重构改名而破坏原有连接
-
灵活性更高
- 可以方便地使用Lambda表达式
- 支持动态连接/断开
- 能够指定不同的连接类型(如跨线程的QueuedConnection)
命名约定自动连接的局限性
虽然Qt提供了on_对象名_信号名
这种命名约定来自动连接信号槽(通过QMetaObject::connectSlotsByName
),但这种方式的缺点包括:
-
隐式连接不够直观
- 连接关系分散在代码各处,难以追踪
- 新开发者可能不了解这种"魔法"行为
-
重构风险
- 修改UI对象名称时容易破坏现有连接
- 缺乏编译时检查,运行时才能发现错误
-
灵活性受限
- 难以实现复杂的连接逻辑
- 不支持Lambda表达式等现代C++特性
最佳实践建议
-
优先使用显式
connect
// 推荐 - Qt5新式语法 connect(ui->pushButton, &QPushButton::clicked, this, &MyWidget::handleButtonClick);
-
对于简单UI逻辑,可适度使用Lambda
connect(ui->pushButton, &QPushButton::clicked, [this](){// 处理点击逻辑 });
-
避免完全依赖命名约定的自动连接
- 即使使用UI设计器生成的代码,也应检查确认连接关系
-
保持一致性
- 在项目中统一采用显式连接风格
- 在代码审查中检查连接方式
结论
虽然Qt框架提供了多种连接信号槽的方式,但显式使用connect
函数能够带来更好的代码可维护性和更少的运行时错误。特别是在大型项目或团队协作中,显式声明对象间的通信关系远比依赖隐式命名约定更为可靠。
相关文章:
QT —— 信号和槽(槽函数)
QT —— 信号和槽 信号和槽信号(Signal)槽(Slot)声明方式工作原理连接方式1. 传统连接方式(Qt4风格)2. 新式连接方式(Qt5风格) 区分槽函数和信号通过QtCreator生成信号槽代码自动生成槽函数显式连接的优势命名约定自动连接的局限性最佳实践建议结论 我们之前对QT,有…...
ROS2模块库概览
一、核心通信与基础库(最常用) 客户端库 rclcpp (ROS Client Library for C) 核心API:create_node(), create_publisher(), create_subscription()高级特性: 生命周期节点:通过rclcpp_lifecycle实现configure/activate…...
HADOOP——序列化
1.创建一个data目录在主目录下,并且在data目录下新建log.txt文件 2.新建flow软件包,在example软件包下 FlowBean package com.example.flow;import org.apache.hadoop.io.Writable;import java.io.DataInput; import java.io.DataOutput; import java.i…...
第五章 5.2ESP32物联网应用:HTTP与Web服务器详细教学
本文将详细讲解如何在ESP32上搭建Web服务器,通过HTTP协议实现远程控制LED灯。每行代码均有详细注释,适合零基础学习。 一、HTTP协议基础 HTTP是客户端(浏览器)和服务器之间的通信协议,常用请求方法: GET&a…...
c++11 绑定器bind
文章目录 std::bind 使用总结(C11)1. 绑定普通函数2. 使用占位符 _1, _2,调用时传参数3. 绑定类的成员函数(类外)4. 绑定类的成员函数(类内)5. 占位符结合成员函数小结 std::bind 使用总结&…...
实现时间最优轨迹生成/轨迹规划方法(TOTG),不使用moveit,可用于ROS驱动机械臂FollowJointTrajectoryGoal()
前言 在我的这篇文章:https://blog.csdn.net/weixin_45702459/article/details/139293391?spm1011.2415.3001.5331中,写了不使用moveit来ros驱动机械臂的方法,也就是用FollowJointTrajectoryGoal()来进行一系列点的关节运动,其实…...
2025年推荐使用的开源大语言模型top20:核心特性、选择指标和开源优势
李升伟 编译 随着人工智能技术的持续发展,开源大型语言模型(LLMs)正变得愈发强大,使最先进的AI能力得以普及。到2025年,开源生态系统中涌现出多个关键模型,它们在各类应用场景中展现出独特优势。 大型语言…...
高并发多级缓存架构实现思路
目录 1.整体架构 3.安装环境 1.1 使用docket安装redis 1.2 配置redis缓存链接: 1.3 使用redisTemplate实现 1.4 缓存注解优化 1.4.1 常用缓存注解简绍 1.4.2 EnableCaching注解的使用 1.4.3使用Cacheable 1.4.4CachePut注解的使用 1.4.5 优化 2.安装Ngin…...
Qt 的 事件队列
Qt 的 事件队列 是其核心事件处理机制之一,用于管理和分发系统与用户生成的事件(如鼠标点击、键盘输入、定时器、信号槽中的队列连接等)。理解 Qt 的事件队列对多线程、界面响应以及异步处理尤为关键。 一、Qt 的事件处理模型概览 Qt 是基于…...
html-css样式
1. 所有类型为文本的 元素的样式 指定所有类型为文本的 元素的样式 /* 文本框的样式 */ input[type"text"] { font-size: 25px;width: 80px; /* 文本框的宽度 */ padding: 25px; } font-size:字体大小 width:文本框宽度 padding&#…...
Qemu-STM32(十五):STM32F103加入Flash控制器
概述 本文主要描述了在Qemu平台中,如何添加STM32F103的Flash控制器模拟代码。 参考资料 STM32F1XX TRM手册,手册编号:RM0008 添加步骤 1、在hw/arm/Kconfig文件中添加STM32F1XX_FLASH,如下所示: 号部分为新增加内容 diff -…...
设计模式(责任链模式)
责任链模式 模板模式、策略模式和责任链模式,这三种模式具有相同的作用:复用和扩展,在实际的项目开发中比较常用,特别是框架开发中,我们可以利用它们来提供框架的扩展点,能够让框架的使用者在不修改框架源…...
【Mac-ML-DL】深度学习使用MPS出现内存泄露(leaked semaphore)以及张量转换错误
MPS加速修改总结 先说设备:MacBook Pro M4 24GB 事情的起因是我在进行深度学习的时候想尝试用苹果自带的MPS进行训练加速,修改设备后准备开始训练,但是出现如下报错: UserWarning: resource_tracker: There appear to be 1 leak…...
Hadoop集群部署教程-P5
Hadoop集群部署教程-P5 Hadoop集群部署教程(续) 第十七章:安全增强配置 17.1 认证与授权 Kerberos认证集成: # 生成keytab文件 kadmin -q "addprinc -randkey hdfs/masterEXAMPLE.COM" kadmin -q "xst -k hdfs.…...
Github 2FA(Two-Factor Authentication/两因素认证)
Github 2FA认证 多因素用户认证(Multi-Factor Authentication),基本上各个大互联网平台,尤其是云平台厂商(如:阿里云的MFA、华为云、腾讯云/QQ安全中心等)都有启用了,Github算是搞得比较晚些了。 双因素身…...
Spark大数据分析与实战笔记(第四章 Spark SQL结构化数据文件处理-05)
文章目录 每日一句正能量第4章 Spark SQL结构化数据文件处理章节概要4.5 Spark SQL操作数据源4.5.1 Spark SQL操作MySQL4.5.2 操作Hive数据集 每日一句正能量 努力学习,勤奋工作,让青春更加光彩。 第4章 Spark SQL结构化数据文件处理 章节概要 在很多情…...
使用 Azure AKS 保护 Kubernetes 部署的综合指南
企业不断寻求增强其软件开发和部署流程的方法。DevOps 一直是这一转型的基石,弥合了开发与运营之间的差距。然而,随着安全威胁日益复杂,将安全性集成到 DevOps 流水线(通常称为 DevSecOps)已变得势在必行。本指南深入探…...
遵守 Vue3 的单向数据流原则:父组件传递对象 + 子组件修改对象属性,安全地实现父子组件之间复杂对象的双向绑定示例代码及讲解
以下是针对 父组件传递对象 子组件修改对象属性 的完整示例代码,同时遵守 Vue3 的单向数据流原则: 1. 父组件代码 (ParentComponent.vue) vue <template><!-- 通过 v-model 传递整个对象 --><ChildComponent v-model"formData&qu…...
Unchained 内容全面上链,携手 Walrus 迈入去中心化媒体新时代
加密新闻媒体 Unchained — — 业内最受信赖的声音之一 — — 现已选择 Walrus 作为其去中心化存储解决方案,正式将其所有媒体内容(文章、播客和视频)上链存储。Walrus 将替代 Unchained 现有的中心化存储架构,接管其全部历史内容…...
20.3 使用技巧2
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 20.3.3 修改表头单元格 设置列表头单元格的内容: 一是可以通过 DataGridView.Columns[列号].HeaderCell来获得对应列的单…...
【Axure绘制原型】小图标使用技巧
获取小图标的网站:https://www.iconfont.cn/ 搜索相关图标 点击下载-复制SVG代码 回到Axure软件中粘贴,此时会显示出图片 在Axure软件中右键-变换图片-转换为形状 即可...
音视频之H.265/HEVC预测编码
H.265/HEVC系列文章: 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 预测编码是视频编码中的核心技术之一。对于视频信号来说,一幅图像内邻近像素之间有着较强的空间相关性,相邻图像之…...
无人机遥感与传统卫星遥感:谁更适合你的需求?
在对地观测领域,无人机遥感和卫星遥感是两种重要的技术手段,各自具有独特的技术原理、性能特点和应用优势。本文将从技术原理、性能特点和应用场景三个方面,对无人机遥感和卫星遥感进行系统对比,帮助读者全面了解两种技术的差异与…...
学习笔记—C++—模板初阶
目录 模板初阶 泛型编程 函数模板 模版概念 函数模版格式 模版的原理 函数模板的实例化 模版参数的匹配规则 类模板 模板初阶 泛型编程 使用函数重载虽然可以实现,但是有一下几个不好的地方: 1. 重载的函数仅仅是类型不同,代码复…...
【Python进阶】字典:高效键值存储的十大核心应用
目录 前言:技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现(10个案例)案例1:基础操作案例2:字典推导式…...
充电宝项目中集成地图地址解析功能梳理
文章目录 MongoDB数据库引入pom依赖配置yaml配置文件参考POJOXLocationRepositoryservice服务方法 腾讯地图接口申请api key配置api key启动类配置RestTemplate控制层服务层 MongoDB数据库 MongoDB对应经纬度的查询具体很好的支持. 引入pom依赖 <dependency><group…...
算法基础(以acwing讲述顺序为主,结合自己理解,持续更新中...)
文章目录 算法的定义一、基础算法排序二分高精度前缀和与差分双指针算法位运算离散化区间合并 算法的定义 这是我从百度上面搜的定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系…...
栈实现队列
栈实现队列 用栈实现队列:C 语言代码解析栈的基本实现栈的初始化栈的销毁入栈操作检查栈是否为空出栈操作获取栈顶元素获取栈中元素个数 用栈实现队列队列的创建入队操作出队操作获取队首元素检查队列是否为空队列的销毁 总结 用栈实现队列:C 语言代码解…...
Redis原理与Windows环境部署实战指南:助力测试工程师优化Celery调试
引言 在分布式系统测试中,Celery作为异步任务队列常被用于模拟高并发场景。而Redis作为其核心消息代理,其性能和稳定性直接影响测试结果。本文将深入解析Redis的核心原理,主要讲解Windows环境部署redis,为测试工程师提供一套完整…...
HWDeviceDRM的三个子类,HWPeripheralDRM HWTVDRM HWVirtualDRM
在很多采用 DRM 架构的 Android 平台(尤其是 QTI 平台,比如 sdm / display-hal 模块中),HWDeviceDRM 是一个基类,抽象了所有类型的 Display 输出设备的共通 DRM 行为,而它有三个常见的子类,对应…...
金融 IC 卡 CCRC 认证:从合规到业务安全的升级路径
在金融科技飞速发展的当下,金融 IC 卡作为现代金融交易的重要载体,广泛应用于各类支付场景,从日常的购物消费到线上金融理财,其安全性直接关系到用户的资金安全和金融机构的稳定运营。CCRC(中国网络安全审查技术与认证…...
微硕WSP6949 MOS管在强排热水器中的应用与市场分析
微硕WSP6949 MOS管在强排热水器中的应用与市场分析 一、引言 强排热水器作为一种常见的家用电器,其核心部件之一是驱动电路,而MOS管作为驱动电路中的关键元件,其性能直接影响到热水器的运行效率和稳定性。微硕半导体推出的WSP6949 MOS管&am…...
文件操作(二进制文件)
C中对文件操作需要包含头文件 #include<fstream> 文件类型分为两类: 1. 文本文件:文件以文本对应的 ASCII 码形式存储在计算机中 2. 二进制文件:文件以文本的二进制形式存储在计算机中,用户一 般不能直接读懂 文件…...
ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(输入类外设之按键Button)
ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(输入类外设之按键Button) 版本信息: ESP-ADF v2.7-65-gcf908721 简介 本文档详细分析ESP-ADF中的输入类外设实现机制,包括按键(button)、触摸(touch)和ADC按键(a…...
HOW - 企业团队自建 npm 仓库
文章目录 一、明确需求二、选型:常用方案三、Verdaccio 搭建步骤1. 安装 Node.js 环境2. 全局安装 verdaccio3. 启动服务4. 配置(可选)5. 用户登录与发布四、团队使用方式1. 使用 `.npmrc` 文件统一配置2. 发布范围包(Scoped packages)五、权限控制六、进阶集成七、测试和…...
键值对和Map的区别
数组里存储键值对和使用Map(在不同语言里也被叫做字典、哈希表等)存在多方面的区别,下面从多个维度进行分析,同时给出C#和C的代码示例。 区别分析 1. 查找效率 数组存储键值对:查找特定键的值时,通常需要…...
CS61A:STRING REPRESENTATION
Python 规定所有对象都应该产生两种不同的字符串表示形式:一种是人类可解释的文本,另一种是 Python 可解释的表达式。字符串的构造函数 str 返回一个人类可读的字符串。在可能的情况下,repr 函数会返回一个计算结果相等的 Python 表达式。rep…...
AI编程新纪元:GitHub Copilot、CodeGeeX与VS2022的联合开发实践
引言:AI编程时代的到来 在软件开发领域,我们正站在一个历史性的转折点上。GitHub Copilot、CodeGeeX等AI编程助手的出现,结合Visual Studio 2022的强大功能,正在重塑代码编写的本质。这不仅是工具层面的革新,更是开发范式的根本转变。能够有效利用这些AI工具的开发者将跨…...
iOS崩溃堆栈分析
文章目录 一、背景二、获取崩溃日志三、使用 dSYM 文件符号化堆栈信息1. 准备 dSYM 文件2. 符号化方法使用 Xcode使用 atos 命令 一、背景 在 iOS 开发中,分析崩溃日志和堆栈信息是调试的重要环节。上线APP往往只能获取到堆栈信息无法获取到具体的崩溃日志…...
kafka服务端和springboot中使用
kafka服务端和springboot中使用 一、kafka-sever安装使用 下载kafka-server https://kafka.apache.org/downloads.html 启动zookeeper zookeeper-server-start.bat config\zookeeper.properties 启动kafka-server kafka-server-start.bat config\server.properties创建主…...
05-DevOps-Jenkins自动拉取构建代码
新建Gitlab仓库 先在Gitab上创建一个代码仓库,选择创建空白项目 安装说明进行填写,然后点击创建项目 创建好的仓库是空的,什么都没有 新建一个springboot项目,用于代码上传使用。 只是为了测试代码上传功能,所以代码…...
win7/win10/macos如何切换DNS,提升网络稳定性
本篇教程教您如何在Windows10、Windows8.1、Windows7、MacOS操作系统切换DNS,以提升系统的稳定性,获得更好的操作体验。 Windows10及Windows8.1 1、右键单击“此计算机”,然后选择“属性”。进入Windows系统界面后,选择左侧的“…...
【正点原子STM32MP257连载】第四章 ATK-DLMP257B功能测试——A35M33异核通信测试
1)实验平台:正点原子ATK-DLMP257B开发板 2)浏览产品:https://www.alientek.com/Product_Details/135.html 3)全套实验源码手册视频下载:正点原子资料下载中心 第四章 ATK-DLMP257B功能测试——A35&M33…...
maven如何解决jar包依赖冲突
maven如何解决jar包依赖冲突 1.背景2.报错信息3.解决思路3.1.查找jsqlparser冲突3.2.发现冲突3.2.解决冲突 4.Dromara Warm-Flow 1.背景 在ruoyi-vue项目集成Warm-Flow过程中,需要把mybatis升级为mybatis-plus,按照Warm-Flow常见问题中升级过程…...
过往记录系列 篇六:国家队护盘历史规律梳理
文章目录 系列文章护盘触发条件与时间规律护盘信号识别特征市场反应规律退出策略历史演变系列文章 过往记录系列 篇一:牛市板块轮动顺序梳理 过往记录系列 篇二:新年1月份(至春节前)行情历史梳理 过往记录系列 篇三:春节行情历史梳理 过往记录系列 篇四:年报月行情历史梳…...
string的模拟实现 (6)
目录 1.string.h 2.string.cpp 3.test.cpp 4.一些注意点 本篇博客就学习下如何模拟实现简易版的string类,学好string类后面学习其他容器也会更轻松些。 代码实现如下: 1.string.h #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include <…...
多模态思维链AI医疗编程:从计算可持续性到开放域推理的系统性解决方案
多模态思维链AI医疗编程:从计算可持续性到开放域推理的系统性解决方案 医疗AI领域的多模态思维链技术正在重塑临床决策支持、医学影像分析和医疗流程优化的范式。本指南从计算可持续性、错误传播控制、伦理安全防护和通用性扩展四大维度,系统解析医疗大模型落地落地的关键要…...
BTS7960 直流电机控制程序
/*************正转逻辑*****************/ LEN1 REN1 while() { LPWN0 DELAY LPWM1 DELAY } /************反转逻辑******************/ LEN1 REN1 while() { RPWN0 DELAY RPWM1 DELAY } /******************************/ /***2025 测试直流电机正反转past…...
vue3 uniapp vite 配置之定义指令
动态引入指令 // src/directives/index.js import trim from ./trim;const directives {trim, };export default {install(app) {console.log([✔] 自定义指令插件 install 触发了!);Object.entries(directives).forEach(([key, directive]) > {app.directive(…...
Mysql-JDBC
JDBCUtils public class JDBCUtils {/*** 工具类的构造方法一般写成私有*/private JDBCUtils(){}//静态代码块再类加载的时候执行,且执行一次static{try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackT…...