Qt之信号和槽的机制

news/2024/5/1 17:51:42/文章来源:https://blog.csdn.net/atomy_iiii/article/details/137432948

前言       

        在 C++ 中,对象与对象之间产生联系要通过调用成员函数的方式。但是在 Qt中,Qt提供了一种新的对象间的通信方式,即信号和槽机制。在GUI编程中,通常希望一个窗口部件的一个状态的变化会被另一个窗口部件知道,为了实现这种效果且取代老式的回调函数,信号和槽机制应运而生,Qt通过 QObject 提供信号和槽的功能。
        信号和槽的核心原理很简单,当某个事件发生之后,如按钮检测到自己被单击了一下,它就会广播出一个信号。如果有对象对这个信号感兴趣,就使用连接函数,将想要处理的信号和自己的一个函数(称为槽函数)进行绑定并处理这个信号。也就是说,当信号被发出时,与之连接的槽即函数会自动被回调。


信号和槽的使用 

        槽的本质就是类的成员函数,其参数可以是任意类型,可以是虚函数,可以被重载。槽通常和信号连接在一起,当信号被发出时,与这个信号连接的槽函数就会被调用,其语法如下。

connect(sender, SIGNAL(signal), receiver, SLOT(slot));

具体参数如下:

  • sender:发出信号的对象。
  • signal:发送对象发出的信号。
  • receiver:接收信号的对象。
  • slot:接收对象在接收到信号之后所需要调用的函数。

        参数中的 sender 就是指向发送信号的对象的指针,receiver 是指向包含槽函数的对象的指针。signal是被发送的信号,slot是接收信号后调用的槽函数,均为不带参数的函数名。SIGNAL()和SLOT()会将其参数转换为字符串,即将函数名转换为字符串,将这个字符串传入 connect()中。

信号和槽的连接比较随意,一个信号可以连接多个槽。
connect(sender, SlGNAL(sianal), receiverA, SLOT(slotA));
connect(sender, SlGNAL(signal), receiverB, SLOT(slotB));也可以多个信号连接同一个槽。
connect(senderA, SIGNAL(signalA), receiver, SLOT(slot));
connect(senderB, SlGNAL(signalB), receiver, SLOT(slot));一个信号还可以连接另外一个信号。
connect(sender, SIGNAL(signalA), receiver, SlGNAL(signalB));当 sender对象发送信号给signalA时,触发receiver对象发送信号给signalB。同时,信号和槽之间的连接可以被移除。
disconnect(sender, SlGNAL(signal),receiver, SLOT(slot));

 Qt 信号和槽机制的优缺点如下:

  • Ot的信号和槽机制的引用可减少程序员编写的代码量。
  • Qt的信号可以对应多个槽(它们的调用顺序随机),也可以多个槽映射一个信号
  • Qt的信号和槽的建立与解除绑定十分自由。
  • 信号和槽同真正的回调函数比起来,时间的耗损还是很大的,在嵌入式实时系统中应当慎用。
  • 信号和槽的参数限定很多,如不能携带模板类参数、不能出现宏定义等。

 用一个例子来解释一下信号和槽的机制:

 新建一个基类 QWidget的 Qt 图形应用项目。

 在widgt.h文件中:

#ifndef WIDGT_H
#define WIDGT_H
#include<QPushButton>
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class widgt; }
QT_END_NAMESPACE
class widgt : public QWidget
{Q_OBJECT//只有继承了QObject类的类,才具有信号和槽;//宏QOBJECT是任何实现信号、槽或属性的强制性要求
public:widgt(QWidget *parent = nullptr);~widgt();
private:Ui::widgt *ui;QPushButton button;
};
#endif // WIDGT_H

在widgt.cpp文件中:

#include "widgt.h"
#include "ui_widgt.h"
widgt::widgt(QWidget *parent): QWidget(parent), ui(new Ui::widgt)
{this->resize(200,200);//修改默认的窗口尺寸button.setParent(this);// 绑定窗口和按钮button.setText("关闭窗口");// 按钮框中文本button.move(48,64);// 定义按钮的位置,以左上角为原点,px 为单位connect(&button,&QPushButton::pressed,this,&widgt::close);
}
widgt::~widgt()
{delete ui;
}

在main.cpp文件中:

#include "widgt.h"
#include <QApplication>
int main(int argc, char *argv[])
{QApplication a(argc, argv);widgt w;w.show();return a.exec();
}

        在这些代码中,button是信号的发送方;信号为QPushButton基类定义的pressed信号;信号接收方为 widgt w,即在构造函数中写为 this;槽函数为基类QWidget定义的 close()函数。这样,在单击“close”按钮时,该按钮 button会发送一个pressed信号,pressed信号会触发w中继承的 close()函数,实现结束程序的功能。 


自定义信号和槽函数

         connect()函数可用来连接系统提供的信号和槽。但是,Qt的信号和槽机制并不是仅能使用系统提供的那部分,程序员也可设计自己的信号和槽。

        首先,创建一个基于基类 QWidget的 Qt图形应用项目,添加一个新的类,类名为“Widget”继承于 Qt 的基类 QWidget。

 在widgt.h文件中:

#ifndef WIDGET_H
#define WIDGET_H
#include <QLabel>
#include <QPushButton>
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget *parent = nullptr);void MySlot();//定义~Widget();
private:Ui::Widget *ui;QPushButton button;QLabel label;
};
#endif // WIDGET_H

 在widgt.cpp文件中:

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{this->resize(240,320);button.setParent(this);button.move(40,50);button.setText("更换内容");label.setParent(this);label.move(40,100);label.setText("更换前");connect(&button,&QPushButton::pressed,this,&Widget::MySlot);
}
void Widget::MySlot()
{label.setText("更换后");
}
Widget::~Widget()
{delete ui;
}

在main.cpp文件中

#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

结果:

 


自定义信号和槽函数的要点

自定义槽函数要点如下。

  • 槽函数可以传入参数,但没有返回值。
  • 在 Qt5 中,任何成员函数、静态成员函数、全局函数及 Lambda 表达式都可以作为槽函数。与信号函数不同,槽函数必须自己完成实现代码。槽函数就是普通的成员函数,因此也会受到public、private 等访问控制关键字的影响。( 如果信号是私有的,这个信号就不能在类的外面连接,而类中本来就可以直接传递,因此这种限制也就没有任何意义。)

 自定义信号和槽需要注意的事项有以下几个。

  • 发送者和接收者都需要 QObject的派生类(当然,槽函数是全局函数、Lambda 表达式等无须接收者的时候除外 )。
  • 使用 signals 标记信号,信号是一个函数声明,返回 void,不需要实现函数代码。
  • 使用 emit 在恰当的位置发送信号。
  • 可以在 main.cpp 中使用QObject::connect()函数连接信号和槽函数。
  • 任何成员函数、静态成员函数、全局函数及Lambda 表达式都可以作为槽函数。

 Q_OBJECT

        在Qt中,如果一个类要使用信号和槽的功能,就必须在其中声明Q_OBJECT,类的定义的第一行就写上了 Q_OBJECT。不管是不是使用信号和槽,都应该添加 O_OBJECT宏,这个宏为类提供了信号和槽机制、国际化机制以及Qt提供的不基于 C++ RTTI的反射能力。其他很多操作都会依赖于这个宏,即使类中不需要使用信号和槽,也需要添加这个宏,否则会出现编译错误。

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

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

相关文章

怎样关闭浏览器文件下载安全病毒中检测功能

怎样关闭浏览器文件下载安全病毒中检测功能 有时候需要通过浏览下载一些特殊文件&#xff0c;浏览器会提示有病毒&#xff0c;终止下载并且自动删除文件。 以为是浏览器的问题&#xff0c;用 chrome、Edge、firefox 三种浏览器下载均失败。 尝试关闭了所有浏览器安全防护也不行…

防止邮箱发信泄露服务器IP教程

使用QQ邮箱,网易邮箱,189邮箱,新浪邮箱,139邮箱可能会泄露自己的服务器IP。 泄露原理&#xff1a;服务器通过请求登录SMTP邮箱服务器接口&#xff0c;对指定的收件人发送信息。 建议大家使用商业版的邮箱&#xff0c;比如阿里云邮箱发信等 防止邮件发信漏源主要关注的是确保邮件…

MySQL innoDB存储引擎多事务场景下的事务执行情况

一、背景 在日常开发中&#xff0c;对不同事务之间的隔离情况等理解如果不够清晰&#xff0c;很容易导致代码的效果和预期不符。因而在这对一些存在疑问的场景进行模拟。 下面的例子全部基于innoDB存储引擎。 二、场景&#xff1a; 2.1、两个事务修改同一行记录 正常来说&…

Linux JDK修改不生效

原JDK8&#xff0c;现需要切换为JDK11&#xff0c;环境变量已经修改为11&#xff0c;但java -version还是显示8。 ln -s -f /home/jdk-11.0.19/bin/java

稀碎从零算法笔记Day45-LeetCode:电话号码的字母组合

题型&#xff1a;映射、回溯算法、递归 链接&#xff1a;17. 电话号码的字母组合 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出…

AI大模型引领未来智慧科研暨ChatGPT自然科学高级应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

基于Springboot中小企业设备管理系统设计与实现(论文+源码)_kaic

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

TensorFlow学习之:深度学习基础

神经网络基础 神经网络是深度学习的核心&#xff0c;它们受人脑的结构和功能启发&#xff0c;能够通过学习大量数据来识别模式和解决复杂问题。神经网络的基本工作原理包括前向传播和反向传播两个阶段。 前向传播&#xff08;Forward Propagation&#xff09; 前向传播是神经…

AI大模型之ChatGPT科普(深度好文)

目录 训练ChatGPT分几步&#xff1f; 如何炼成ChatGPT&#xff1f; 如何微调ChatGPT? 如何强化ChatGPT? 如何调教ChatGPT? AI思维链是什么&#xff1f; GPT背后的黑科技Transformer是什么&#xff1f; Transformer在计算机视觉上CV最佳作品&#xff1f; ChatGPT是人…

修复 Windows 上的 PyTorch 1.1 github 模型加载权限错误

问题: 在 Windows 计算机上执行示例 github 模型加载时,生成了 master.zip 文件的权限错误(请参阅下面的错误堆栈跟踪)。 错误堆栈跟踪: 在[4]中:en2de = torch.hub.load(pytorch/fairseq, transformer.wmt16.en-de, tokenizer=moses, bpe=subword_nmt) 下载:“https://…

【R基础】一组数据计算均值、方差与标准差方法及意义

【R基础】一组数据计算均值、方差与标准差方法及意义 均值、方差与标准差是用来描述数据分布情况 均值&#xff1a;用来衡量一组数据整体情况。 数据离散程度度量标准&#xff1a; 方差&#xff08;均方&#xff0c;s^2&#xff0c;总体参数&#xff0c;离均差平方和&#…

实用工具推荐:如何使用MechanicalSoup进行网页交互

在当今数字化时代&#xff0c;网页交互已经成为日常生活和工作中不可或缺的一部分。无论是自动填写表单、抓取网页数据还是进行网站测试&#xff0c;都需要一种高效而可靠的工具来实现网页交互。而在众多的选择中&#xff0c;MechanicalSoup作为一种简单、易用且功能强大的Pyth…

GitLab教程(一):安装Git、配置SSH公钥

文章目录 序一、Git安装与基本配置&#xff08;Windows&#xff09;下载卸载安装基本配置 二、SSH密钥配置 序 为什么要使用代码版本管理工具&#xff1a; 最近笔者确实因为未使用代码版本管理工具遇到了一些愚蠢的问题&#xff0c;笔者因此认为代码版本管理工具对于提高团队…

基于FPGA的以太网相关文章导航

首先需要了解以太网的一些接口协议标准&#xff0c;常见的MII、GMII、RGMII时序&#xff0c;便于后续开发。 【必读】从MII到RGMII&#xff0c;一文了解以太网PHY芯片不同传输接口信号时序&#xff01; 介绍一款比较老的以太网PHY芯片88E1518&#xff0c;具有RGMII接口&#xf…

防止狗上沙发,写一个浏览器实时识别目标检测功能

家里有一条狗&#x1f436;&#xff0c;很喜欢乘人不备睡沙发&#x1f6cb;️&#xff0c;恰好最近刚搬家 狗迎来了掉毛期 不想让沙发上很多毛。所以希望能识别到狗&#xff0c;然后播放“gun 下去”的音频&#x1f4e3;。 需求分析 需要一个摄像头&#x1f4f7; 利用 chrome…

openHarmony 如何从API9升级到API10

最近用从官方下载的DevEco Studio3.1开发小app, 需要用到第三方库&#xff0c;加载第三方库&#xff0c;并添加代码&#xff0c;编译时如下错误&#xff1a; hvigor Finished :entry:defaultGenerateMetadata… after 3 ms hvigor ERROR: Failed :entry:defaultMergeProfile… …

微信小程序页面交互综合练习 (重点:解决“setData of undefined”报错问题)

一、写一个注册表单&#xff0c;点击“注册”按钮将用户输入的数据带到服务器&#xff0c;并且能在控制台显示参数。 &#xff08;1&#xff09;首先&#xff0c;我需要在vscode里面创建一个简易的node.js服务器 //第一步:引入http模块 var http require(http); //第二步:创建…

算法刷题Day30 | 332.重新安排行程、51. N皇后、37. 解数独

目录 0 引言1 重新安排行程1.1 我的解题1.2 更好的解法 2 N皇后2.1 我的解题 3 解数独3.1 我的解题3.2 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a5; 标题&#xff1a;算法刷题Day30 | 332.重新安排行程、51. N皇后、37. …

【图论】详解链式前向星存图法+遍历法

细说链式前向星存图法 首先要明白&#xff0c;链式前向星的原理是利用存边来进行模拟图。 推荐左神的视频–建图、链式前向星、拓扑排序 比方说有这样一张图&#xff0c;我们用链式前向星来进行模拟时&#xff0c;可以将每一条边都进行编号&#xff0c;其中&#xff0c;红色的…

刷题DAY49 | LeetCode 121-买卖股票的最佳时机 122-买卖股票的最佳时机II

121 买卖股票的最佳时机&#xff08;easy&#xff09; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取…