(6)元对象系统与信号与槽机制

news2024/11/27 22:30:50

1. 元对象系统

        元对象系统是一个基于标准C++的扩展,为Qt提供了信号与槽机制、实时类型信息、动态属性系统。

 什么是元对象

        在计算机科学中,元对象是这样一个东西:它可以操纵、创建、描述、或执行其他对象。元对象描述的对象称为基对象。元对象可能存在这样的信息:基础对象的类型、接口、类、方法、属性、变量、控制结构等。

元对象系统组成

QObject

        QObject是 QT 对象模型的核心,绝大部分的 Qt类都是从这个类继承而来。

Q_OBJECT

        Q_OBJECT宏必须出现在类定义的私有部分,用来开启信号和槽、动态属性系统,或Qt元对象系统提供的其他服务。

#define Q_OBJECT \
public: \
    QT_WARNING_PUSH \
    Q_OBJECT_NO_OVERRIDE_WARNING \
    static const QMetaObject staticMetaObject; \
    virtual const QMetaObject *metaObject() const; \
    virtual void *qt_metacast(const char *); \
    virtual int qt_metacall(QMetaObject::Call, int, void **); \
    QT_TR_FUNCTIONS \
private: \
    Q_OBJECT_NO_ATTRIBUTES_WARNING \
    Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
    QT_WARNING_POP \
    struct QPrivateSignal {}; \
    QT_ANNOTATE_CLASS(qt_qobject, "")

MOC

         Qt 的信号和槽机制是采用标准 C++ 来实现的。该实现使用 C++ 预处理器和 Qt 所包括 的 moc(元对象编译器)。元对象编译器读取应用程序的头文件,并生成必要的代码,以支 持信号和槽机制。

        元对象编译器 moc(meta object compiler)对 C++文件中的类声明进行分析并产生用 于初始化元对象的 C++代码,元对象包含全部信号和槽的名字以及指向这些函数的指针。

        moc 读 C++源文件,如果发现有 Q_OBJECT 宏声明的类,它就会生成另外一个 C++源文件,这个新生成的文件中包含有该类的元对象代码。例如,假设我们有一个头文件Widget.h,在这个文件中包含有信号或槽的声明,然后在同名源文件 Widget.cpp中包含这个头文件,并实现类,那么在编译之前 moc 工具就会根据该文件自动生成一个名为moc_Widget.cpp 的 C++源文件并将其提交给编译器。

2. 信号与槽机制

        信号与槽是 Qt 框架引以为傲的机制之一。所谓信号与槽,实际就是观察者模式(发布-订阅模式)。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。信号和槽是Qt特有的信息传输机制,是Qt设计程序的重要基础,它可以让互不干扰的对象建立一种联系。

 信号与槽的本质

        信号是由对象发送出去的消息,信号实际上是一个特殊的函数,不需要由程序员实现,而是由Qt的Qt Meta Object System实现的。

        槽实际上就是普通的函数,成员函数、全局函数、静态函数、lambda函数都可以作为槽函数。

        当我们把对象的信号和槽绑定在一起之后,当信号触发时,与之绑定的槽函数将会自动调用,并把信号的参数传递给槽函数。

信号与槽的绑定

        在Qt中信号和槽函数都是独立的个体,本身没有任何联系,但是由于某种特性需求我们可以将二者连接到一起,好比牛郎和织女想要相会必须要有喜鹊为他们搭桥一样。

信号与槽绑定使用QObject::connent()函数实现,其基本格式如下:

[static] QMetaObject::Connection connect(
     const QObject *sender, 
     const QMetaMethod &signal, 
     const QObject *receiver, 
     const QMetaMethod &method,
 	, Qt::ConnectionType type = Qt::AutoConnection)
     
 [static] QMetaObject::Connection connect(
     const QObject *sender, 
     PointerToMemberFunction signal, 
     Functor functor)

参数解析:

  • sender:信号发送者,需要传递一个QObject族的对象指针

  • signal:发出的具体信号,需要传递一个函数指针

  • receiver:信号接收者,需要传递一个QObject族的对象指针

  • method:接收到信号之后,信号接收者处理动作,需要传递一个函数指针(槽函数)

  • type:第一个connect函数独有参数,表示信号和槽的连接类型;有默认值,一般不需修改。

 信号与槽的断开

        信号与槽连接之后,还可以断开连接,断开之后,信号出发之后,槽函数就不会调用了。注意,信号与槽的断开时必须与连接时的参数一致。当然也可以直接使用connect函数的返回值断开连接。

bool disconnect(const QObject *sender, 
                const QMetaMethod &signal, 
                const QObject *receiver, 
                const QMetaMethod &method)
bool disconnect(const QMetaObject::Connection &connection)

3. 标准信号与槽的使用

使用信号与槽机制必须在该类的定义私有部分包含Q_OBJECT宏。

        在Qt提供的很多类中都可以对用户触发的某些特定事件进行检测,  当事件被触发后就会产生对应的信号, 这些信号都是Qt类内部自带的, 因此称之为标准信号。

        同样的,在Qt的很多类内部为我了提供了很多功能函数,并且这些函数也可以作为触发的信号的处理动作,有这类特性的函数在Qt中称之为标准槽函数。

#include <QApplication>
#include <QWidget>

//去掉控制台
#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")

class Widget : public QWidget
{
	Q_OBJECT							// 使用信号与槽机制必须包含此宏
public:
	Widget(QWidget* parent = nullptr)
		:QWidget(parent)
	{
		setWindowTitle("窗口标题");		// 设置窗口标题
		resize(640, 480);				// 设置窗口大小

	}
	~Widget()
	{

	}
private:
};

int main(int argc, char* argv[]) {

	QApplication a(argc, argv);
	Widget w;
	w.show();

	return a.exec();
}
#include "main.moc"

如上代码将会得到一个窗口:

当在Widget构造函数中添加以下代码会出现:

Widget(QWidget* parent = nullptr)
	:QWidget(parent)
{
	setWindowTitle("窗口标题");		// 设置窗口标题
	resize(640, 480);				// 设置窗口大小

	//按钮的使用
	QPushButton* btn = new QPushButton;
	btn->setText("Button");
	btn->show();
}

按钮为什么没有显示在窗口上面而是独立显示,那是因为没有给按钮设置父对象,给按钮设置父对象之后就不需要调用show()了,按钮会跟窗口一起显示。

//按钮的使用
QPushButton* btn = new QPushButton;
btn->setText("Button");
btn->setParent(this);

 然后尝试使用信号和槽实现点击按钮关闭窗口的效果:

class Widget : public QWidget
{
	Q_OBJECT							// 使用信号与槽机制必须包含此宏
public:
	Widget(QWidget* parent = nullptr)
		:QWidget(parent)
	{
		setWindowTitle("窗口标题");		// 设置窗口标题
		resize(640, 480);				// 设置窗口大小

		m_btn = new QPushButton("Button", this);
		//关联信号与槽
		auto con = connect(m_btn, &QPushButton::clicked, this, &QWidget::close);

	}
	~Widget()
	{

	}
private:
	QPushButton* m_btn = nullptr;
};

int main(int argc, char* argv[]) {

	QApplication a(argc, argv);
	Widget w;
	w.show();

	return a.exec();
}
#include "main.moc"

使用disconnect函数解除信号与槽的绑定

//关联信号与槽
auto con = connect(m_btn, &QPushButton::clicked, this, &QWidget::close);

//解绑信号与槽
disconnect(m_btn, &QPushButton::clicked, this, &QWidget::close);
//disconnect(con);    // 与上一行代码一样的效果

使用帮助文档查看标准的信号与槽

直接使用帮助文档查看控件,如果该控件没有信号或者槽就继续查找它的父类是否有。

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

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

相关文章

记一次搭建备库,使用连接串主库无法连接到备库

主库使用连接串连接备库失败 SQL> conn sys/oracleorcldg as sysdba ERROR: ORA-12528: TNS:listener: all appropriate instances are blocking new connections 备库已经建立了静态监听 # listener.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/…

安全寒假第一堂课

一、状态码 200 – 服务器成功返回网页 404 – 请求的网页不存在 503 – 服务器超时 1xx&#xff08;临时响应&#xff09; 表示临时响应并需要请求者继续执行操作的状态码。 100&#xff08;继续&#xff09; 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一…

OpenCV实战(5)——图像运算详解

OpenCV实战&#xff08;5&#xff09;——图像运算详解0. 前言1. 图像基本运算2. 重载图像运算符2.1 加法运算符重载2.2 分割图像通道2.3 完整代码3. 图像重映射3.1 OpenCV 重映射函数3.2 完整代码小结系列链接0. 前言 图像可以以不同的方式进行组合&#xff0c;因为它们是正则…

XGBoost论文阅读

XGBoost: A Scalable Tree Boosting System 目录 XGBoost: A Scalable Tree Boosting System 1.摘要 2.方法 2.1 正则化学习目标 2.2 梯度提升树 2.3 收缩率和列采样 2.4分裂点查找算法 1.摘要 提出了一种新的稀疏性感知算法&#xff0c;用于稀疏数据和加权全图草图&a…

Python教程:什么是三级模式和二级映像?

美国国家标准学会(American National Standards Institute,ANSI)所属的标准计划与需求委员会&#xff08;Standards Planning and Requirements Committee,SPARC)在1971年公布的研究报告中提出了ANSI-SPARC体系结构&#xff0c;即三级模式结构&#xff08;或称为三层体系结构&a…

ArcGIS基础实验操作100例--实验53导出线、面要素的坐标值

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验53 导出线、面要素的坐标值 目录 一、实验背景 二、实验数据 三、实验步骤 &#xf…

笔记杂项(一)

都是踩过的坑&#xff0c;趟过的水。 ubuntu虚拟机终端字体太小的设置方法&#xff1a;ubuntu18.04调整终端字体大小 这个方法试试看&#xff1a;https://zhuanlan.zhihu.com/p/139305626 容器里面编译内核代码&#xff0c;进程被杀掉的原因是触发了内核OOM killer&#xff0c…

干货| app自动化测试之Andriod微信小程序的自动化测试

随着微信小程序的功能和生态日益完善&#xff0c;很多公司的小程序项目页面结构越来越多&#xff0c;业务逻辑也越来越复杂。如何做好小程序的自动化测试就成为测试同学普遍面临的一大痛点难题。微信小程序小程序内嵌于微信内部&#xff0c;页面包含 Native 原生元素和 Web 元素…

华为防火墙与二层交换机对接配置VLAN上网设置

拓扑图 一、防火墙设置 1、G1/0/0接口设置IP&#xff0c;G1/0/1接口切换二层口设置VLAN&#xff0c;G1/0/0 桥接了本地无线网卡来模拟公网地址 <USG6000V1>sys [USG6000V1]sys FW1 [FW1]un in en# 设置公网IP [FW1]int g1/0/0 [FW1-GigabitEthernet1/0/0]ip addr 192.1…

package.json配置解读之入门

文章目录前言一、描述配置nameversionrepositorydescriptionkeywordslicenseauthor二、文件配置filestypemainbrowsermoduleexportsworkspaces三、脚本配置scriptsconfig四、结语前言 package.json是每个前端项目都会有的json文件&#xff0c;位于项目的根目录中。很多脚手架在…

RHCE(chrony服务器)

chrony服务器 chrony服务器是一个开源自由的网络时间协议NTP的客户端和服务器的软件&#xff0c;他能让计算机保持系统时钟和时钟服务器保持同步&#xff0c;让计算机保持精确的时间&#xff0c;chrony也可以作为服务端软件为其他计算机提供时间同步服务 chrony由两部分组成&…

openAI--十拳剑助你做AI时代的弄潮儿

AI它厉害&#xff08;diao&#xff09;吗&#xff1f; 最近大家玩chatgpt还好吗&#xff1f; 有被它的恋爱情商暴击到吗&#xff1f; 有没有觉得那在leetcode上所向无敌的技巧都是浮云吗&#xff1f; 今天&#xff0c;我为大家带来十个很好的AI平台。这一篇先介绍一下&…

【远程桌面】nomachine下载安装使用教程、zerotier下载安装使用教程超详细

文章目录一、软件介绍二、NoMachine远程桌面1.Windows下载安装使用2.Linux下载安装使用3.Android下载安装使用4.ARM下载安装使用&#xff08;未实践&#xff09;三、ZeroTier内网穿透0.官网注册账户1.Windows下载安装使用2.Linux下载安装使用3.Android下载安装使用4.ARM下载安装…

Android 学习 - 不完善

SharedPreference 共享参数用法 SharedPreference 是 Android 的一个轻量级存储工具, 采用的存储结构是Key-Value的键值对方式. 共享参数的存储介质是符合XML规范的配置文件. 保存路径是: /data/data/应用包名/shared_prefs/文件名.xml 利用元数据配置快捷菜单 (1)元数据的met…

【阶段二】Python数据分析Pandas工具使用11篇:探索性数据分析:数据的检验:卡方检验与t检验

本篇的思维导图: 探索性数据分析:数据的检验 卡方检验 在实际的学习或工作中,也会碰到关于离散型变量之间的探索性分析,如两个离散变量之间是否相互独立。对于该问题的解答,就需要运用统计学中的卡方检验了。卡方检验属于非参数的检验方法,其原假设是两个离散变…

Spring——最全Spring目录

&#x1f4eb;作者简介&#xff1a;zhz小白 公众号&#xff1a;小白的Java进阶之路 专业技能&#xff1a; 1、Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理 2、熟悉Java基础&#xff0c;并精通多线程的开发&#xff0c;熟悉JVM原理&#xff0c;具备⼀定的线…

2022 IoTDB Summit:IoTDB PMC侯昊男《Apache IoTDB首创时序顺乱序分离存储引擎 IoTLSM》...

12 月 3 日、4日&#xff0c;2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本&#xff0c;并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例&#xff0c;深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…

Flutter项目中添加Webview(八)使用JavaScript渠道

借助JavascriptChannel&#xff0c;您的应用可以在WebView的JavaScript上下文中注册回调处理程序&#xff0c;可以调用这些回调处理程序将值传递回应用的Dart代码。在此步骤中&#xff0c;您将注册一个使用 SMLHttpRequest的结果调用SnackBar。 将WebViewStack类更新如下所示&…

Mysql的锁(自用笔记)

笔记(https://www.bilibili.com/video/BV1Kr4y1i7ru) 什么是锁? mysql中有哪几种锁 表级锁 表级锁-表锁 write lock 写锁, 加锁客户端,可以读写操作, 其他客户端不能 读,写操作 表级锁-元数据锁 一个例子,事务中,增删改查时候,会自动加入元数据锁,不允许对表结构进行修改 …

Keras model.predict输出的概率值转换为类别

问题&#xff1a;使用Keras做分类任务&#xff0c;model.predict预测得到的值为每个类别的概率值&#xff0c;而不是类别。 源码&#xff1a; y_test_pred model.predict(x_test, batch_size256, verbose1)解决&#xff1a; import numpy as np y_test_pred model.predict(…