QT元对象系统特性详细介绍(信号槽、类型信息、动态设置属性)(注释)

目录

一、元对象系统简介

二、信号和槽

三、类型信息

 四、动态设置属性


一、元对象系统简介

QT中的元对象系统Q_OBJECT并不是C++标准代码,因此在使用时需要QT的MOC(元对象编译器)进行预处理,MOC会在编译时期读取C++代码中的特定宏(如Q_OBJECT),再由标准的C++编译器进行重新编译。

Q_OBJECT的使用:必须要在类中定义元对象系统Q_OBJECT 宏才能使用(在类定义时,如果没有指定public或者private,则默认为private(私有))。程序运行时,moc会扫描此类,并生成元对象信息,包括但不限于类名、父类、属性、信号、槽函数等;

Q_OBJECT的特性:

  • 类型信息:Qt使用元对象系统来存储关于对象的信息,如类名和父类。
  • 属性系统:支持动态的属性机制,允许在运行时查询和修改对象的属性。
  • 信号和槽的动态连接:元对象系统允许在运行时创建和解除信号与槽之间的连接。

二、信号和槽

(1)信号与槽是对象间进行通信的机制,使用QObject::connect函数连接信号和槽时,元对象系统会在运行时查找信号(signals)和槽(slots),并建立连接。使用方式如下:

QtWidgetsApplication3.h

#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication3.h"
#include <QObject> //包含头文件,以使用信号槽class QtWidgetsApplication3 : public QMainWindow
{//启用Qt的元对象系统,允许使用信号和槽等特性Q_OBJECTpublic:QtWidgetsApplication3(QWidget *parent = nullptr);~QtWidgetsApplication3();
private:Ui::QtWidgetsApplication3Class ui;
signals:    //声明信号void testsignal();
};class obj : public QObject //继承QObject使用信号槽
{//启用Qt的元对象系统,允许使用信号和槽等特性Q_OBJECT public: //声明构造函数,接受一个QObject指针作为父对象obj(QObject* parent = nullptr);
public slots: //声明槽void testslot();
};

QtWidgetsApplication3.cpp

#include "QtWidgetsApplication3.h"
QtWidgetsApplication3::QtWidgetsApplication3(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);obj* qobj = new obj(this);  //创建obj的实例QObject::connect(this,&QtWidgetsApplication3::testsignal, qobj,&obj::testslot); //连接信号和槽emit testsignal();          //触发信号
}void obj::testslot()
{qDebug() << "obj::testslot()";
}QtWidgetsApplication3::~QtWidgetsApplication3()
{}obj::obj(QObject* parent)
{}

 运行效果:

(2)信号和槽的五种写法与使用方式

(3)信号和槽之间的关系:

1、信号的参数类型必须与槽函数参数的类型相对应

signals:      //声明信号void testsignal(int);public slots: //声明槽void testslot(int);emit testsignal(100);  //触发信号

2、信号的参数个数大于等于槽函数的参数个数

signals:      //声明信号void testsignal(int,int);public slots: //声明槽void testslot(int);emit testsignal(100,100);  //触发信号

3、信号和槽函数之间的关系是多对多,信号也可以 连接到另一个信号上

signals:    //声明信号void testsignal(int);
public slots: //声明槽void testslot(int);
public slots: //声明槽void testslot2(int);QObject::connect(this,&QtWidgetsApplication3::testsignal, qobj,&obj::testslot); //连接信号和槽QObject::connect(this,&QtWidgetsApplication3::testsignal, qobj,&obj::testslot2); //连接信号和槽emit testsignal(100);  //触发信号

4、信号和槽的连接机制原理:通过QObject::connect来实现的

QObject::connect(sender, &Sender::signal, receiver, &Receiver::slot);
//在上述代码中,sender对象的signal信号与receiver对象的slot槽函数被连接起来。

5、信号和槽的连接类型:

  • 直接连接(Direct Connection):这种连接方式类似于自动连接,但是即使在不同线程中也会立即调用槽函数。需要注意的是,这种方式可能导致竞态条件,因为它绕过了事件队列,所以使用时需要特别小心。
  • 队列连接(Queued Connection):在这种模式下,信号的发射不会立即导致槽函数的执行。相反,信号会被放入事件队列中,在下一个事件循环开始时才执行槽函数。这种方式常用于跨线程通信,因为可以避免直接从非GUI线程中调用可能会修改GUI组件的方法。
  • 自动连接(Auto Connection):这是默认的连接方式。当信号被发射时,Qt会立即调用相关的槽函数。这种方式适用于大多数情况,因为它是最快的方式,并且不需要额外的线程同步机制。
//直接连接
connect(button, &QPushButton::clicked, this, &MyWidget::handleClick, Qt::DirectConnection);
//队列连接
connect(button, &QPushButton::clicked, this, &MyWidget::handleClick, Qt::QueuedConnection);
//自动连接
connect(button, &QPushButton::clicked, this, &MyWidget::handleClick);

6、信号发射原理

emit mySignal(data);
//在上述代码中,当调用emit mySignal(data);时,所有连接到mySignaal的槽函数都会被调用。

7、槽函数调用过程

当一个信号被发射时,Qt负责按连接顺序调用与该信号连接的所有槽函数。

8、信号发射与线程

  • 信号可以安全地跨线程发射,如果信号接收者位于不同线程,Qt会自动将信号的处理放入目标线程的事件循环中,确保线程安全。
  • 信号的发射和槽的执行会自动适应线程间的通信机制,通过Qt的事件循环和消息队列机制来实现。
  • 线程安全:Qt的跨线程信号和槽机制是线程安全的,开发者无需担心常见的多线程问题,如竞态条件和死锁。
  • 自动同步:Qt处理所有线程间的通信细节,确保数据在线程间传递时的完整性和一致性。

7、信号和槽异步调用

当信号和槽位于不同线程时,Qt使用事件循环来实现异步调用。信号的发射将产生一个事件,该事件被放入目标线程的事件队列中。当事件循环处理到这个事件时,与之关联的槽函数被调用。

8、事件队列的角色

事件队列在信号和槽的跨线程通信中起着至关重要的作用。每个线程都有自己的事件队列和事件循环。当一个线程向另一个线程发出信号时,这个信号被封装成一个事件,然后被加入接收线程的事件队列。这确保了即使在高度并发的环境下,槽函数的执行也是线程安全的。

三、类型信息

Q_OBJECT 宏使得类可以通过 QMetaObject获取详细的运行时类型信息。这些信息包括类名、父类、信号、槽、属性等。

QtWidgetsApplication4.h

#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication4.h"
#include <QMetaObject>   //获取元对象
#include <QMetaMethod>   //信号与槽
#include <QMetaProperty> //属性
#include <QDebug>
#include <QObject>class QtWidgetsApplication4 : public QMainWindow
{Q_OBJECT
public:QtWidgetsApplication4(QWidget *parent = nullptr);~QtWidgetsApplication4();
private:Ui::QtWidgetsApplication4Class ui;
signals:void mysignal(int); //设置类的信号
private slots: void myslot(int);   //设置类的槽
private:int myProperty=false;
};

QtWidgetsApplication4.cpp

#include "QtWidgetsApplication4.h"QtWidgetsApplication4::QtWidgetsApplication4(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);//获取元对象const QMetaObject *metaObject = this->metaObject();//打印类名qDebug() << metaObject->className();//打印所有信号qDebug() << "Signals:";for (int i = 0; i < metaObject->methodCount(); i++){QMetaMethod  method = metaObject->method(i);qDebug() << method.name();}//打印所有槽qDebug() << "Slots:";for (int i = 0; i < metaObject->methodCount(); i++){QMetaMethod  method = metaObject->method(i);if (method.methodType() == QMetaMethod::Slot)qDebug() << method.name();}//打印所有属性qDebug() << "Properties:";for (int i = 0; i < metaObject->propertyCount(); i++){QMetaProperty property = metaObject->property(i);qDebug() << property.name();}
}QtWidgetsApplication4::~QtWidgetsApplication4()
{}void QtWidgetsApplication4::myslot(int)
{}

运行效果:

 四、动态设置属性

在QT中,动态属性设置的添加与修改,可以应用于数据绑定、状态管理、主题样式、事件处理等;例如:可以将 UI 控件的属性与模型数据绑定,这样当模型数据发生变化时,UI 控件的属性会自动更新。

QtWidgetsApplication5.cpp

#include "QtWidgetsApplication5.h"QtWidgetsApplication5::QtWidgetsApplication5(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);//获取当前对象的元对象const QMetaObject *metaObject = this->metaObject();//打印类名qDebug() << metaObject->className();//动态设置属性this->setProperty("dynamicProperty",QVariant(42));//动态获取属性QVariant value = this->property("dynamicProperty");qDebug() << "dynamicProperty:" << value.toInt();//检查属性是否存在QVariant checkValue =this->property("dynamicProperty");if (checkValue.isValid()) { qDebug() << "Property exists and its value is:" << checkValue.toInt(); }else { qDebug() << "Property does not exist."; }//修改属性this->setProperty("dynamicProperty", QVariant(100));//获取修改后的属性值value = this->property("dynamicProperty");qDebug() << "Modified dynamic property value:" << value.toInt();//删除属性this->setProperty("dynamicProperty",QVariant());checkValue = this->property("dynamicProperty");if (checkValue.isValid()) {qDebug() << "Property exists and its value is:" << checkValue.toInt();}else {qDebug() << "Property has been 'deleted'.";}
}QtWidgetsApplication5::~QtWidgetsApplication5()
{}

QtWidgetsApplication5.h

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication5.h"
#include <QMetaObject>   //获取元对象
#include <QMetaMethod>   //信号与槽
#include <QMetaProperty> //属性
#include <QDebug>class QtWidgetsApplication5 : public QMainWindow
{Q_OBJECT
public:QtWidgetsApplication5(QWidget *parent = nullptr);~QtWidgetsApplication5();
private:Ui::QtWidgetsApplication5Class ui;
};

运行效果:

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

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

相关文章

java反序列化之CommonCollections6利⽤链的学习

一、源起 前文学习CC1链和URLDNS链的学习&#xff0c;同时学习过程中知道cc1受jdk版本的限制&#xff0c;故而进一步分析cc6链的利用过程&#xff0c;这个利用链不受jdk版本的限制&#xff0c;只要commons collections小于等于3.2.1&#xff0c;都存在这个漏洞。 ps&#xff1…

SpringBoot中间件Docker

Docker&#xff08;属于C/S架构软件&#xff09; 简介与概述 1.Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux …

【ubuntu】Ubuntu20.04安装中文百度输入法

1.download 百度Linux输入法-支持全拼、双拼、五笔 2.unzip unzip Ubuntu_Deepin-fcitx-baidupinyin-64.zip 3.setting 3.1 setting fcitx sudo apt install aptitude sudo aptitude install fcitx-bin fcitx-table fcitx-config-gtk fcitx-frontend-all sudo aptitude in…

Cocos_鼠标滚轮放缩地图

文章目录 前言一、环境二、版本一_code2.分析类属性方法详细分析详细分析onLoad()onMouseWheel(event)详细分析 总结 前言 学习笔记&#xff0c;请多多斧正。 一、环境 通过精灵rect放置脚本实现鼠标滚轮放缩地图。 二、版本一_code import { _decorator, Component, Node }…

使用Buildpacks构建Docker镜像

## 使用Buildpacks构建Docker镜像 ![](../assets/运维手册-Buildpacks-Buildpacks.io.png) ### Buildpacks简介 与Dockerfile相比&#xff0c;Buildpacks为构建应用程序提供了更高层次的抽象。具体来说&#xff0c;Buildpacks&#xff1a; * 提供一个平衡的控制&#xff0c;…

【Python】Conda离线执行命令

以下链接证明了想要离线使用conda命令的方法 启用离线模式 — Anaconda documentation 基本上大部分的命令都会提供网络选项 例如creat命令 conda create — conda 24.7.1 文档 - Conda 文档

多区域OSPF路由协议

前言 之前也有过关于OSPF路由协议的博客&#xff0c;但都不是很满意&#xff0c;不是很完整。现在也是听老师讲解完OSPF路由协议&#xff0c;感触良多&#xff0c;所以这里重新整理一遍。这次应该是会满意的 一些相关概念 链路状态 链路指路由器上的一个接口&#xff0c;链路状…

毕设分享 基于协同过滤的电影推荐系统

文章目录 0 简介1 设计概要2 课题背景和目的3 协同过滤算法原理3.1 基于用户的协同过滤推荐算法实现原理3.1.1 步骤13.1.2 步骤23.1.3 步骤33.1.4 步骤4 4 系统实现4.1 开发环境4.2 系统功能描述4.3 系统数据流程4.3.1 用户端数据流程4.3.2 管理员端数据流程 4.4 系统功能设计 …

信息安全工程师(28)机房安全分析与防护

前言 机房安全分析与防护是一个复杂而细致的过程&#xff0c;涉及到物理安全、环境控制、电力供应、数据安全、设备管理、人员管理以及紧急预案等多个方面。 一、机房安全分析 1. 物理安全威胁 非法入侵&#xff1a;未经授权的人员可能通过门窗、通风口等进入机房&#xff0c;…

【LeetCode】每日一题 2024_10_10 优质数对的总数 I(暴力/哈希)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;优质数对的总数 I 代码与解题思路 简单题先暴力~ 直接对着题意模拟即可&#xff0c;力扣上只要是标着简单标签的题目&#xff0c;不用犹豫&#xff0c;直接对他使用暴力吧&#xff01; …

LabVIEW混合控制器质量检测

随着工业自动化水平的提高&#xff0c;对控制器的精度、稳定性、可靠性要求也在不断上升。特别是在工程机械、自动化生产、风力发电等领域&#xff0c;传统的质量检测方法已无法满足现代工业的高要求。因此&#xff0c;开发一套自动化、精确、可扩展的混合控制器质量检测平台成…

Pikachu-Cross-Site Scripting-xss盲打

xss盲打&#xff0c;不是一种漏洞类型&#xff0c;而是一个攻击场景&#xff1b;在前端、或者在当前页面是看不到攻击结果&#xff1b;而是在后端、在别的页面才看到结果。 登陆后台&#xff0c;查看结果&#xff1b;

Extreme Compression of Large Language Models via Additive Quantization阅读

文章目录 Abstract1. Introduction2. Background & Related Work2.1. LLM量化2.2. 最近邻搜索的量化 3.AQLM:Additive Quantization for LLMs3.1. 概述3.1.0 补充**步骤说明****举例说明** 3.2. 阶段1&#xff1a;代码的波束搜索3.3. 阶段2&#xff1a;码本更新3.4. 阶段3&…

Qt Creator 通过python解释器调用*.py

全是看了大佬们的帖子&#xff0c;结合chatGPT才揉出来。在此做个记录。 安装python在Qt Creator *.pro 文件中配置好环境来个简单的example.py调用代码安装pip添加opencv等库调用包含了opencv库的py代码成功 *.pro配置&#xff1a; INCLUDEPATH C:\Users\xuanm\AppData\Lo…

操作系统中的并发控制——使用条件变量同步

本期主题&#xff1a; 操作系统中的并发控制&#xff0c;条件变量 往期链接&#xff1a; linux设备驱动中的并发操作系统中的多线程问题——原子操作、自旋锁的底层实现操作系统并发控制——使用互斥锁实现同步 操作系统并发控制之条件变量同步 1. 问题描述2. 条件变量的API讲…

云栖实录 | Hologres3.0全新升级:一体化实时湖仓平台

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 姜伟华 | 阿里云智能集团资深技术专家、Hologres 负责人 丁 烨 | 阿里云智能集团产品专家、Hologres 产品负责人 活动&#xff1a; 2024 云栖大会 - 商用大数据计算与分析平台论…

Python中的数据可视化:从入门到进阶

数据可视化是数据分析和科学计算中的重要环节&#xff0c;它通过图形化的方式呈现数据&#xff0c;使复杂的统计信息变得直观易懂。Python提供了多种强大的库来支持数据可视化&#xff0c;如Matplotlib、Seaborn、Plotly等。本文将从基础到进阶&#xff0c;详细介绍如何使用这些…

[单master节点k8s部署]31.ceph分布式存储(二)

Ceph配置 Ceph集群通常是一个独立的存储集群&#xff0c;可以部署在 Kubernetes 集群之外。Ceph 提供分布式存储服务&#xff0c;能够通过 RADOS、CephFS、RBD&#xff08;块存储&#xff09;、和 RGW&#xff08;对象存储&#xff09;等方式与 Kubernetes 集成。即使 Ceph 部…

基于深度学习的手势控制模型

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 1. 项目简…

Nexpose 6.6.271 发布下载,新增功能概览

Nexpose 6.6.271 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Sep 26, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.or…