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

news2024/11/25 6:40:58

目  录

一、元对象系统简介

二、信号和槽

三、类型信息

四、动态设置属性


一、元对象系统简介

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、obj,互相通信。

QtWidgetsApplication3.h

#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication3.h"
#include <QObject> //包含头文件,以使用信号槽

class QtWidgetsApplication3 : public QMainWindow
{
    //启用Qt的元对象系统,允许使用信号和槽等特性
    Q_OBJECT //默认私有
public:
    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.coloradmin.cn/o/2205332.html

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

相关文章

暗语源码 复现佛禅翻译系统v2升级版源码

与佛论禅翻译系统 一个翻译佛论的娱乐系统&#xff0c;类似于核心价值观加密 此为升级版&#xff0c;每次加密得到的结果不一样&#xff0c;配合箴言功能&#xff0c;更加安全 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89874751 更多资源下载&a…

现代易货交易:重塑价值,引领未来交易新风尚

在当今经济蓬勃发展的背景下&#xff0c;一种新颖的交易模式——现代易货交易&#xff0c;正逐渐崭露头角并赢得市场的认可。这一模式不仅对传统物品交换方式进行了革新&#xff0c;更在物品价值的评估与交换手段上展现出创新性。那么&#xff0c;现代易货交易究竟是何方神圣&a…

基于SSM的旅游网站【附源码】

基于SSM的旅游网站&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概要设计 4.2 系统功能结构设计 4.3 数据库设计 4.3.1 数据库E-R图设计 4.3.2 数据库表结构设计 5 系统实现 5.1 管理员功能介绍 5.1.1 用户管理 5.1.2 …

比较模拟数据

模拟数据检查器可以比较来自工作区、文件或模拟中的运行和单个信号的数据和元数据。可以使用公差来分析比较结果&#xff0c;并可以通过指定信号属性和比较约束来配置比较行为。此示例使用从模型slexAircraftExample的模拟中记录的数据&#xff0c;演示了以下内容&#xff1a; …

云栖实录 | MaxCompute 迈向下一代的智能云数仓

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 张治国 | 阿里云智能集团研究员、阿里云 MaxCompute 负责人 谢德军&#xff5c;阿里云智能集团资深技术专家 于得水&#xff5c;阿里云智能集团资深技术专家 谌鹏飞&#xff5c…

SpringMVC源码-@ControllerAdvice和 @InitBinder注解源码讲解

1.ControllerAdvice修饰的类何时被加载扫描 被ControllerAdvice修饰的类是作用于全局的 initStrategies 初始化springmvc的9大组件 initStrategies:531, DispatcherServlet (org.springframework.web.servlet) onRefresh:514, DispatcherServlet (org.springframework.web.se…

在线答题系统怎么做?一文为您揭秘!

在线答题系统是一种利用网络技术实现的答题平台&#xff0c;具有高效、便捷、灵活等特点&#xff0c;被广泛应用于教育、培训、考试、竞赛等场景。以下是其详细介绍&#xff1a; 一、 基本功能&#xff1a; 题目录入&#xff1a;支持多种方式录入题目&#xff0c;如手动输入、…

Android15之解决:Dex checksum does not match for dex:services.jar问题(二百三十五)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

前端接收到的日期格式为 2021-12-07T16:44:53.298+00:00 怎么办?

在写项目的时候&#xff0c;给前端发送了一个 Date 类型的数据,发现格式不对&#xff1a; 可以通过在application 配置文件中进行如下配置&#xff1a; spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8 前端在获取就发现格式正确

登高赏菊迎重阳,与家人共乐同度佳节。

在金风送爽的重阳佳节&#xff0c;让我们登高远望&#xff0c;与亲人共赏菊花&#xff0c;共享团圆时光。愿清风明月&#xff0c;带来幸福与好运&#xff0c;让我们心怀感恩&#xff0c;笑对人生&#xff0c;共度这个美好的重阳节日&#xff01;

中安未来 OCR:合同抽取的高效利器

在数字化办公的时代&#xff0c;高效处理文档成为了众多企业的迫切需求。中安未来 OCR 技术以其强大的功能脱颖而出。 中安未来的 OCR 技术能够准确识别各种文档中的文字信息&#xff0c;其中合同抽取功能尤为实用。对于企业来说&#xff0c;合同管理至关重要。传统的合同处理方…

如何设置 GitLab 密码过期时间?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 60天专业…

CLIP——多模态预训练模型介绍

CLIP: Contrastive Language-Image Pre-training CLIP: 对比语言-图像预训练 CLIP的是由 OpenAI 2021年在 Learning Transferable Visual Models From Natural Language Supervision【利用文本的监督信号训练一个迁移能力强的视觉模型】中提出的一种多模态预训练模型&#xff…

AI荣耀时刻!2024诺贝尔物理奖、化学奖双双归属AI界

全球科学界迎来了2024最为瞩目的时刻——诺贝尔奖揭晓&#xff01;当诺贝尔物理奖和化学奖这两大科学殿堂的最高荣誉同时聚焦在人工智能&#xff08;AI&#xff09;领域时&#xff0c;AI技术无疑再次被推向了神坛&#xff0c;成为全球瞩目的焦点&#xff01;这一历史性的时刻&a…

2024年【焊工(初级)】最新解析及焊工(初级)模拟试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 焊工&#xff08;初级&#xff09;最新解析根据新焊工&#xff08;初级&#xff09;考试大纲要求&#xff0c;安全生产模拟考试一点通将焊工&#xff08;初级&#xff09;模拟考试试题进行汇编&#xff0c;组成一套焊…

来势汹汹,Eva Gamaiun超现实版权画时隔一年连发两案再次维权

案件基本情况起诉时间&#xff1a;2024-9-23、2024-9-24案件号&#xff1a;2024-cv-08763、2024-cv-08804原告&#xff1a;Eva Gamaiun原告律所&#xff1a;keith起诉地&#xff1a;伊利诺伊州北部法院品牌介绍Eva Gamayun&#xff0c;1990年出生&#xff0c;是一位自学成才的混…

vue项目 子组件在打开时调用父组件传过来的props里的数据

1 分析: 父组件在加载时就会加载子组件,所以此时调不到数据, 我们可以利用父组件内子组件的ref属性,获取子组件的方法, 在父组件的触发方法中调用直接传值 例: 父组件: //父组件事件AttributesRelations(row){this.dialogForm rowthis.$refs.AttributesRelationsRef.Attribu…

华为 HCIP-Datacom H12-821 题库 (35)

&#x1f423;博客最下方微信公众号回复题库,领取题库和教学资源 &#x1f424;诚挚欢迎IT交流有兴趣的公众号回复交流群 &#x1f998;公众号会持续更新网络小知识&#x1f63c; 1.一个 Route-Policy 下可以有多个节点&#xff0c;设备在调用Route-Policy时按顺序开始匹配 …

【最新华为OD机试E卷-支持在线评测】智能成绩表(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

如何才能使绩效管理和薪酬管理完美结合?

如何才能使绩效管理和薪酬管理完美结合&#xff1f; 企业内部管理中&#xff0c;绩效考核与薪酬设计是人力资源管理的两大核心支柱。薪酬设计不仅是工资分配的基石&#xff0c;更是激发员工潜能的关键工具&#xff1b;绩效考核则作为评估标尺&#xff0c;衡量如销售额、服务满…