Qt之信号和槽的机制

前言       

        在 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.mzph.cn/news/796481.shtml

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

相关文章

12.自定义的多帧缓存架构

1.简介 在数字图像处理中&#xff0c;经常需要用到的一个架构就是多帧缓存。视频流中需要用到多帧缓存来防止帧撕裂现象&#xff0c;图像处理中也需要帧差法来做移动目标检测。因此一个多帧缓存架构在图像系统的设计中是十分重要的。 2.多帧缓存 在视频流中&#xff0c;通常不…

前端开发全景指南:语言与框架的精粹

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

解决IDEA下载mysql驱动太慢

下载驱动 下载页 解压后&#xff0c;提取**.jar**文件&#xff0c;放到一个目录下(你自己决定这个目录) 打开IDEA项目&#xff0c;点击右侧的数据库选项卡 在打开的页面&#xff0c;点击号 依次选择&#xff1a;数据源->MySQL 在弹出的页面&#xff0c;依次选择&#…

mysql表字段长度扩容分析--MySQL什么情况下拓展字段长度会锁表?

MySQL什么情况下拓展字段长度会锁表&#xff1f; 原生MySQL只支持不跨越256字节的在线扩展&#xff08;online&#xff09;&#xff0c;对于跨越256字节的扩展只支持复制方式&#xff08;copy&#xff09;&#xff0c;扩展时需要锁表且禁止对数据表进行写操作。 字符串的字段是…

Quantinuum与微软携手突破:开创容错量子计算新纪元

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

腾讯云轻量服务器流量不够用了会怎么样?

腾讯云轻量应用服务器是限制月流量的&#xff0c;如果当月流量不够用了&#xff0c;流量超额了怎么办&#xff1f;流量超额后&#xff0c;需要另外支付流量费&#xff0c;如果你的腾讯云账号余额&#xff0c;就会自动扣除对应的流量费&#xff0c;如果余额不足&#xff0c;轻量…

YOLOv7原创独家改进: 小目标 | 注意力 |卷积和注意力融合模块(CAFMAttention) | 2024年4月最新成果

💡💡💡本文独家改进:卷积和注意力融合模块(CAFMAttention),增强对全局和局部特征的提取能力,2024年最新的改进思路 💡💡💡创新点:卷积和注意力巧妙设计 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect前面,增…

深入浅出 -- 系统架构之负载均衡Nginx资源压缩

一、Nginx资源压缩 建立在动静分离的基础之上&#xff0c;如果一个静态资源的Size越小&#xff0c;那么自然传输速度会更快&#xff0c;同时也会更节省带宽&#xff0c;因此我们在部署项目时&#xff0c;也可以通过Nginx对于静态资源实现压缩传输&#xff0c;一方面可以节省带宽…

【Java网络编程】HTTP超文本传输协议

一、HTTP超文本传输协议 HTTP全称为Hyper Text Transfer Protocol超文本传输协议&#xff0c;它是基于TCP传输协议构建的应用层协议&#xff0c;作为支撑万维网www的核心协议&#xff0c;为了保证其效率及处理大量事务的能力&#xff0c;因此在设计时&#xff0c;HTTP被制定成为…

lua学习笔记5(分支结构和循环的学习)

print("*****************分支结构和循环的学习******************") print("*****************if else语句******************") --if 条件 then end a660 b670 --单分支 if a<b thenprint(a) end --双分支 if a>b thenprint("满足条件")…

C#操作MySQL从入门到精通(5)——查询数据

前言 在和MySql数据库交互的过程中,查询数据是使用最频繁的操作,本文详细介绍了查询数据的各种操作,包括查询一列数据、 查询两列数据、查询所有列数据、查询不重复的数据、查询指定行数据,绝对是C#操作MySql数据库史上最详细教程,能够帮助小白快速入门以及将这些功能迅速…

京东云4C8G服务器优惠价格418元1年,轻量云主机4核8G配置

京东云服务器优惠活动4C8G服务器配置418元一年&#xff0c;1899元3年&#xff0c;配置为轻量云主机4C8G-180G SSD系统盘-5M带宽-500G月流量&#xff0c;京东云服务器活动页面 jdyfwq.com 可以查看京东云服务器详细配置和精准报价单&#xff0c;活动打开如下图&#xff1a; 轻量…

sharding‐jdbc之分库分表实战

数据库表结构 店铺数据库 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for region -- ---------------------------- DROP TABLE IF EXISTS region; CREATE TABLE region (id bigint(20) NOT NULL COMMENT id,region_…

上位机图像处理和嵌入式模块部署(qmacvisual实时视频)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们测试和练习的时候&#xff0c;大部分情况下都是利用图像进行测试的&#xff0c;但是实际情况下&#xff0c;或者准确一点说&#xff0c;工…

android 制作登录页

项目需要可以直接copy layout.xml <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"…

华为汽车的“计算+通信”电子电气架构

文章目录 整车结构 硬件平台 软件平台 总结展望 整车EEA&#xff08;电子电气架构&#xff09;&#xff0c;按照博世提出的演进路径&#xff0c;大致可以划分为四个阶段&#xff1a;分布式模块阶段、区域控制阶段、中央计算阶段、云计算阶段。示例如下&#xff1a; 本文选取…

【Node.js】短链接

原文链接&#xff1a;Nodejs 第六十二章&#xff08;短链接&#xff09; - 掘金 (juejin.cn) 短链接是一种缩短长网址的方法&#xff0c;将原始的长网址转换为更短的形式。短链接的主要用途之一是在社交媒体平台进行链接分享。由于这些平台对字符数量有限制&#xff0c;长网址可…

c# wpf LiveCharts 绑定 简单试验

1.概要 c# wpf LiveCharts 绑定 简单试验 2.代码 <Window x:Class"WpfApp3.Window2"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schem…

K8S基于containerd做容器从harbor拉取镜

实现创建pod时&#xff0c;通过指定harbor仓库里的镜像来运行pod 检查&#xff1a;K8S是不是用containerd做容器运行时&#xff0c;以及containerd的版本是不是小于1.6.22 kubectl get nodes -owide1、如果containerd小于 1.6.22&#xff0c;需要先升级containerd 先卸载旧的…

Note-模型的特征学习过程分析

模型的学习过程 将数据的特征分为,有用特征和无用特征(噪声).有用特征与任务有关,无用特征与任务无关. 模型的学习过程就是增大有用特征的权重并减少无用特征的权重的过程. 神经网络反向传播过程简化如下: y a 0 x 0 a 1 x 1 , l o s s 0.5 ∗ ( y l a b e l − y ) 2 y …