【Qt】信号与槽(下)

news2024/11/26 14:47:05

目录

自定义信号

 带参数的信号和槽

信号和槽存在的意义

信号与槽的连接方式

一对一

一对多

多对一

意义

信号和槽的其他说明

信号和槽的断开

使用Lambda表达式定义槽函数

信号与槽的优缺点

优点: 松散耦合

缺点: 效率较低


自定义信号

自定义槽函数是非常关键的,在开发中大部分情况都是需要自定义槽函数的。

槽函数,就是用户触发某个操作之后,要进行的业务逻辑

自定义信号,比较少见,在实际开发中很少会需要自定义信号。

信号就对应到用户的某个操作。

在GUI,用户能够进行哪些操作,是可以穷举的,在Qt中内置的信号,基本已经覆盖到了上述所有可能的用户操作。因此使用Qt内置的信号,旧足以应付大部分的开发场景。

widget这个类中虽然没有定义任何信号,由于继承自Qwidget和QObject,这俩个类里面已经提供了一些信号,可以直接使用。

所谓的Qt信号,本质上就是一个”函数“。

        Qt5已经更高版本中,槽函数和普通的成员函数之间已经没有区别;但是信号则是一类特殊的函数:

  1. 只需要写出函数声明,并且告诉Qt这是一个”信号“即可,这个函数的定义,是Qt在编译过程中,自动生成的(自动生成的过程,程序员无法进行干预)。因为信号在Qt中式特殊的机制,Qt生成的信号函数的实现,要配合Qt框架左很多既定的操作。
  2. 作为信号函数,这个函数的返回值,必须式void,有没有参数都可以,甚至也可以支持重载。

这个signals也是Qt自己扩展出来的关键字,在qmake的时候,调用一些代码的分析/生成工具,扫描到类中包含signals这个关键字的时候,此时,就会自动的把下面的函数声明认为是信号,并且给这些信号函数自动的生成函数定义。

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

signals:
    void mySignal();
    
public slots:
    void handleMySignaal();
    
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    connect(this, &Widget::mySignal, this, &Widget::setWindowTitle);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::handleMySignaal()
{
    this->setWindowTitle("自定义信号");
}

建立好联系之后,还需要将信号发送出去。

        对于Qt内置的信号,都不需要手动通过代码来触发,用户在GUI进行某些操作,就会自动触发对应信号(发射信号的代码已经内置到Qt框架中了)。

关键字:emit 发射

发射信号的操作,可以在任意合适的代码中。

这样就可以完成自定义信号了。

也可以通过点击按钮的方式,进行对窗口的编辑。

【注意】其实在Qt5中emit什么都不会做,真正进行操作的都包含在mysignal内部生成的函数定义里面,所以可以舍弃emit,信号也能发送出去,即使如此,在实际开发过程中,建议把emit加上,这可以让代码的可读性更高,更加明显的标识出这里发射自定义的信号。

 带参数的信号和槽

Qt的信号和槽也支持带有参数,同时也可以支持重载。

        此处要求:当信号带有参数的时候,槽的参数必须和信号参数一致,当发射信号的时候,就可以给信号函数传递实参,与之对应的这个参数就会被传递到槽函数里,此时就可以起到让信号给槽传参效果了。

【注意】在C++中声明函数的时候,形参的名字可以不用写。

        信号函数和槽函数必须一致,个数如果不一致也可以,当个数不一致的时候,要求信号参数的个数必须比槽的参数个数多。

传参可以起到复用代码代码的效果,如果有多个逻辑,逻辑上整体一致,但是涉及到的数据不同,就可以通过函数-参数来复用代码,并且在不同的场景中传入不同的参数。

通过这一套信号槽,搭配不同的参数,就可以起到设置不同标题的效果。

        在Qt的很多内置的信号,也是带有参数的,这些参数不是咱们自己传递的。

例如:clicked信号就带有一个参数。

clicked(bool),这个参数表示当前按钮是否处于“选中”状态。这个选中状态对于QPushButton没有意义,但是对于QCheckBox复选框是很有用的。

信号函数的参数个数,超过了槽函数的参数个数,还是可以正常使用的。

如果信号函数的参数个数少于槽函数的参数个数,此时代码无法编译通过。

为什么允许信号的参数比槽的参数多呢?

        一个槽函数,又可能会绑定多个信号。如果严格要求参数个数一致,就意味着信号绑定槽的要求就变高了。换而言之,当下这样的规则,就允许信号和槽之间的绑定更灵活了,有更多的信号可以绑定到这个槽函数上。

如果个数不一致,槽函数就会按照参数顺序,拿到信号的前N个参数。至少要确保,槽函数的每个参数都是有值的。所以要求信号给槽的参数,可以有富裕,但是不能少。

【注意】带有参数的信号,要求信号的参数和槽的参数一致,这里的一致指的是类型一致,个数满足要求(信号的参数个数要对于槽的参数个数)。

在Qt中,如果要让某个类能够使用信号槽(即可以在类中定义信号函数和槽函数),则必须在类最开始的地方,写下Q_OBJECT宏。

        这个事情可以看作是Qt中的硬性规定,这个宏能展开成很多额外的代码。

这里的宏还可以进一步展开,最后展开的效果会得到一系列很复杂的代码,此处就不深入研究了。

如果不加这个宏,代码在编译期间就会出错。

信号和槽存在的意义

所谓的信号和槽,最终要解决的问题,就是响应用户的操作。

信号与槽的连接方式

一对一

主要有俩种形式,分别是:一个信号连接一个槽和一个信号连接一个信号

一对多

一个信号连接多个槽

多对一

多个信号连接一个槽函数 

意义

一个信号,可以connect多个槽函数,一个槽函数也可以被多个信号connect。

        Qt引入信号与槽机制,最本质的目的就是为了能够让信号和槽之间按照“多对多”的方式进行关联。其他GUI框架是不具备这样的特性。但是,随着程序开发的经验变多,在GUI开发过程中,多对多这种情况,其实是”伪需求“,在实际开发中很少用到,绝大部分的情况,一对一就够用了。

信号和槽的其他说明

信号和槽的断开

使用disconnect即可完成断开,disconnect的用法和connect基本一致。

实际使用中,disconnect的使用比较少,大部分情况下把信号和槽连接上之后,就不用等了。

主动断开的目的往往是把信号重新绑定到另一个槽函数上。

  1. 断开原来的信号槽
  2. 重新绑定信号槽。

如果没有disconnect,就会构成一个信号绑定俩个槽函数,触发信号的时候,俩个槽函数都会执行。

使用Lambda表达式定义槽函数

Qt5在Qt4的基础上提高了信号与槽的灵活性,允许使用任意函数作为槽函数。但是如果想要方便的编写槽函数,例如在编写函数的时候连函数名都不想定义,就可以通过Lambda表达式来达到这个目的。

Lambda表达式是C++11增加的特性。在C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。

Lambda表达式的语法格式如下:

其本质上就是一个”匿名对象“,主要应用在”回调函数“场景中。

lambda表达式是一个回调函数,引入了”变量捕获“语法,通过变量捕获,获取到外层作用域中的变量。

在[ ]可以添加下面函数中需要的参数,如果想要使用外层的全部变量就需要[=]。

[=]这个写法的函数就是把上层作用域中的所有变量都给捕获进来。

#include "widget.h"
#include "ui_widget.h"

#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton* button = new QPushButton("按钮" ,this);
    button->move(350, 250);
    connect(button, &QPushButton::clicked, this, [=](){
        this->setWindowTitle("lambda");
        button->setText("lambda");
    });
}

Widget::~Widget()
{
    delete ui;
}

如果对应的槽函数比较简单,而且是一次性使用的,经常会写成lambda形式。

        另外也需要确认捕获到lambda内部的变量是由意义的,例如:无论何时用户点击了按钮,捕获到的变量都能正确使用。

信号与槽的优缺点

优点: 松散耦合

信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了⾃⼰,Qt的信号槽机制保证了信号与槽函数的调⽤。⽀持信号槽机制的类或者⽗类必须继承于QObject类。

缺点: 效率较低

与回调函数相⽐,信号和槽稍微慢⼀些,因为它们提供了更⾼的灵活性,尽管在实际应⽤程序中差别不⼤。通过信号调⽤的槽函数⽐直接调⽤的速度慢约10倍(这是定位信号的接收对象所需的开销;遍历所有关联;编组/解组传递的参数;多线程时,信号可能需要排队),这种调⽤速度对性能要求不是⾮常⾼的场景是可以忽略的,是可以满⾜绝⼤部分场景。

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

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

相关文章

VMware 安装 centos7.9教程

目录 VMware17安包装 1.创建新的虚拟机 2.稍后安装一个系统 3.选择Centos7 4.选择安装位置 5.指定磁盘内存大小 6.自定义硬件 7.编辑内存 8.编辑处理器 9.选择安装镜像位置 10.选择网络适配器 11.播放虚拟机 12.选择语言简体中文 13.选择时区时间 14.最小化安装 …

电机学习-基础知识

文章目录 1 基本物理概念1.1 左手定则1.2 安培定则1.3 感应电动势 2 电机简单分类2.1 直流有刷电机2.2 步进电机2.2.1 步进电机的驱动原理1.相与线2.极性3.步进电机的驱动 2.3 无刷电机2.3.1 充磁方式2.3.2正弦波电动势与梯型电动势 3 编码器3.1 霍尔编码器3.2 光电编码器3.3 增…

TexWorks配置使用latexmk实现增量编译

TexWorks配置使用latexmk实现增量编译 TexWorks默认使用pdfLaTeXMakeIndexBibTeX&#xff0c;修改后&#xff0c;重新编译等待时间较长。本文旨在说明配置TexWorks使用latexmk实现增量式编译&#xff0c;加速编译。 前置条件说明 (1) 通过miktex自动安装了TexWorks及自带pdf…

Docker相关配置记录

Docker相关配置记录 换源 {"registry-mirrors": ["https://dockerhub.icu","https://docker.chenby.cn","https://docker.1panel.live","https://docker.awsl9527.cn","https://docker.anyhub.us.kg","htt…

VisionPro二次开发学习笔记12-使用CogToolGroup控件进行图像检测

本示例演示了如何通过图像数据库使用 CogImageFileTool&#xff0c;并将其放入 CogToolGroup 中&#xff0c;对于数据库中的每个图像运行一次检测. 当用户按下 运行 按钮时&#xff0c;程序执行以下操作&#xff1a; 如果工具组中没有 CogImageFileTools&#xff0c;它将显示一…

Codeforces Pinely Round 4 (Div. 1 + Div. 2) A~G

A.Maximize the Last Element&#xff08;枚举&#xff09; 题意&#xff1a; 给你一个由 n n n个整数组成的数组 a a a&#xff0c;其中 n n n是奇数。 在一次操作中&#xff0c;你将从数组 a a a中删除两个相邻的元素&#xff0c;然后将数组的剩余部分连接起来。例如&…

轻松构建Electron应用:TypeScript与esbuild的完美搭档

简介 使用 TypeScript (TS) 编写 Electron 应用程序带来了许多好处&#xff0c;以下是一些主要优势&#xff1a; 类型安全&#xff1a;TypeScript 是一种静态类型语言&#xff0c;它在编译时检查类型错误&#xff0c;这有助于在开发过程中及早发现潜在的错误。更好的工具支持…

RK3568平台(背光篇)背光调试常见问题

一.屏幕背光概述 背光就是屏幕的从里往照射的光。 LCD 主要由液晶面板、背光、驱动电路等组成&#xff0c;液晶面板不会主动发光&#xff0c;需要背光源才能显示&#xff0c;液晶面板的作用就是通过电压改变某像素光的透过率来显示的&#xff0c;当然此光要求是偏振光&#x…

数据结构(5.5_3)——并查集的进一步优化

Find操作的优化(压缩路径) 压缩路径——Find操作&#xff0c;先找到根节点&#xff0c;再将查找路径上所有结点都挂到根结点下 代码&#xff1a; //Find "查"操作优化&#xff0c;先找到根节点&#xff0c;再进行"路径压缩" int Find(int S[], int x) {…

Shell、C/C++、Python操作环境变量

环境变量 环境变量是一种在操作系统中用于存储信息的机制&#xff0c;这些信息可以被系统进程、应用程序和脚本访问和使用。环境变量在操作系统中的作用类似于一个全局配置参数&#xff0c;它们定义了操作系统的运行环境&#xff0c;包括系统行为、应用程序路径、用户信息等。…

uniapp自定义浮动图标、列表布局

uniapp自定义浮动图标 <button class="fab" @click="goPage"><image src="../../../static/yiyuan.png" mode="" style="width: 60rpx;height:60rpx;"></image></button>.fab {z-index: 100;positi…

TLE4966-3G带方向检测功能的高灵敏度汽车霍尔开关

TLE4966-3G是一款集成电路双霍尔效应传感器&#xff0c;专为使用旋转极轮的高精度应用而设计。通过片上有源补偿电路和斩波器技术实现精确的磁切换点和高温稳定性。 该传感器在Q2提供速度输出&#xff0c;其状态&#xff08;高或低&#xff09;与磁场值相对应。对于超过阈值BO…

小白零基础学数学建模系列-Day3-线性回归模型的构建与评估

文章目录 1 线性回归基础1.1 线性回归概念与应用1.2 数学原理与推导1.3 线性回归的实现 2 案例分析&#xff1a;房价预测2.1 加载数据2.2 数据预处理2.3 探索性数据分析2.4 观察选择特征2.5 准备训练模型的数据2.6 将数据拆分为训练集和测试集2.7 训练和测试模型2.8 模型评估 3…

Ubuntu每次登录都提示有新的更新,apt更新却0个软件需要升级:清空MOTD消息 安装update-notifier-common组件 运行强制更新脚本

问题 每登录ubuntu&#xff0c;都会显示有更新需要注意。 80更新可以立即应用。 这些更新中有 1 个是标准安全更新。 要查看这些附加更新&#xff0c;请运行&#xff1a;apt list --upgradable 然而使用更新命令却提示0可更新 查询了一下&#xff0c;这似乎是MOTD的错误&#x…

Gartner发布2024年网络风险管理成熟度曲线:使网络安全战略与业务目标保持一致的概念、方法、流程和技术

网络风险管理现在是高管和监管机构最关注的问题&#xff0c;它采用多种方法和技术来支持治理、风险管理和合规性。安全和风险管理领导者可以使用此技术成熟度曲线来评估解决方案并做出适当的采用决策。 战略规划假设 到 2026 年&#xff0c;60% 的网络安全职能将实施以业务影响…

【Qt】Qt编程注意事项

目录 Qr中的命名规范 Qt Creator中的快捷键 查询文档的方式 Qt窗口坐标体系 Qr中的命名规范 在学习编程语言阶段&#xff0c;给变量、函数、文件、类命名是非常有讲究的。 命名要有描述性&#xff0c;不要使用abc&#xff0c;xyz这种比较无规律的名字类描述。如果名字比较…

什么是前端微服务,有何优势

随着互联网技术的发展&#xff0c;传统的单体应用架构已经无法满足复杂业务场景的需求。微服务架构的兴起为后端应用的开发和部署提供了灵活性和可扩展性。与此同时&#xff0c;前端开发也经历了类似的演变&#xff0c;前端微服务作为一种新兴的架构模式应运而生。 一、前端微服…

开源web版3D展示工具Online3DViewer

Online3DViewer是一个免费且开源的Web解决方案&#xff0c;它允许用户在浏览器中直接预览和探索3D模型。 以下是关于Online3DViewer的详细介绍&#xff1a; 一、基本概述 定义&#xff1a;Online3DViewer是一个在线3D模型查看器&#xff0c;支持多种3D文件格式&#xff0c;用…

如何评价2023年数学建模国赛?

2023年的赛题已经发布了,ABC三题侧重点不同,但是A题专业性较强,涉及微分方程,以及优化模型,B题题目为多波束测线问题,第一问需要计算,结合函数和几何的相关知识点,问题2涉及到最小路径问题,如下有总结,可以查看相应的模块方法,C题目为“蔬菜类商品的自动定价与补货决…

C++ 哈希使用与底层原理

哈希的概念 哈希是一种建立映射的思想&#xff0c;我们尝试用的数据结构是哈希表 &#xff0c;又称「散列表」&#xff0c;其通过建立键 key 与值 value 之间的映射&#xff0c;实现高效的元素查询。具 体而言&#xff0c;我们向哈希表输入一个键 key &#xff0c;则可以在 &am…