QT属性系统

1 介绍

        Qt中的属性系统是用于为对象添加自定义属性管理这些属性的一种机制。它允许开发者在不修改类定义的情况下,动态地为Qt对象添加新的属性,并且能够对这些属性进行读取设置监听

        属性系统在Qt中是通过Q_PROPERTY宏QObject的元对象系统来实现的。开发者可以通过在QObject派生类中使用Q_PROPERTY宏,将新的属性添加到对象中,并为这些属性定义读取(getter)和设置(setter)方法。

1.1 主要作用总结

        a)自定义属性:通过属性系统,开发者可以向Qt对象中添加自定义的属性,以便存储和访问特定的数据。

        b)属性读写:属性系统允许开发者为属性定义读取和设置方法,使得外部代码可以读取和修改对象的属性值。

        c)属性通知:当属性的值发生变化时,属性系统可以发出信号通知其他代码,从而实现属性的监听和响应。

        d)Qt的元对象系统:属性系统是建立在Qt的元对象系统之上的,这使得属性可以在运行时进行反射操作,比如查询对象的属性列表、获取属性的类型等。

1.2 使用步骤

        步骤1:在QObject派生类中定义属性

        首先,在QObject派生类中使用`Q_PROPERTY`宏来定义属性。`Q_PROPERTY`宏的语法如下:

 Q_PROPERTY(type name(READ getFunction [WRITE setFunction] |MEMBER memberName [(READ getFunction | WRITE setFunction)])[RESET resetFunction][NOTIFY notifySignal][REVISION int | REVISION(int[, int])][DESIGNABLE bool][SCRIPTABLE bool][STORED bool][USER bool][BINDABLE bindableProperty][CONSTANT][FINAL][REQUIRED])

        其中,`type`是属性的数据类型,`name`是属性的名称,`getFunction `是读取属性值的方法,`setFunction`是设置属性值的方法,`notifySignal`是当属性值发生变化时发送的信号。

        例如,定义一个名为`myProperty`的属性,数据类型为`int`:

```cpp
class MyObject : public QObject
{Q_OBJECTQ_PROPERTY(int myProperty READ getMyProperty WRITE setMyProperty NOTIFY myPropertyChanged)public:int getMyProperty() const;void setMyProperty(int value);signals:void myPropertyChanged();
};
```

        步骤2:实现属性的读取和设置方法

        接下来,在类的实现文件中实现属性的读取和设置方法:

```cpp
int MyObject::getMyProperty() const
{return m_myProperty;
}void MyObject::setMyProperty(int value)
{if (m_myProperty != value) {m_myProperty = value;emit myPropertyChanged();}
}
```

        步骤3:连接属性变化信号到槽函数(可选)

        如果希望在属性值发生变化时执行一些操作,可以将属性变化信号连接到槽函数:

```cpp
MyObject obj;
connect(&obj, &MyObject::myPropertyChanged, someSlotFunction);
```

        步骤4:使用属性

```cpp
obj.setMyProperty(42);
int value = obj.getMyProperty();
```

        属性系统提供了可以像操作普通的数据成员一样操作这些自定义属性的方法,同时也可以利用Qt的信号槽系统来监听属性值的变化。这为Qt对象的数据管理提供了一种便捷的方式,并且使得代码更加灵活和可维护。

2 Q_PROPERTY与Meta_Object_system(元对象系统)使用示例

        tperson.h:

#ifndef TPERSON_H
#define TPERSON_H#include <QObject>class TPerson : public QObject
{Q_OBJECTQ_CLASSINFO("author", "luo")Q_CLASSINFO("institution", "Foreland")Q_CLASSINFO("version", "0.10")Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)Q_PROPERTY(QString name MEMBER m_name)Q_PROPERTY(int score MEMBER m_score)
public:explicit TPerson(QString name, QObject *parent = nullptr);~TPerson();int age();//输出年龄的函数void setAge(quint8 age);//设置年龄void increaseAge();  //增加年龄
signals:void ageChanged(int ageValue);
private:QString m_name;int m_age=10;int m_score=79;
};#endif // TPERSON_H

        tperson.cpp:

#include "tperson.h"TPerson::TPerson(QString name, QObject *parent):QObject{parent}, m_name{name}
{
//    this->m_name = name;
}TPerson::~TPerson()
{qDebug("TPerson对象被删除");
}int TPerson::age()
{return m_age;
}void TPerson::setAge(quint8 ageValue)
{if(ageValue != m_age){m_age = ageValue;emit ageChanged(m_age);}}void TPerson::increaseAge()
{++m_age;emit this->ageChanged(m_age);
}

       widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "tperson.h"
#include <QMetaProperty>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;TPerson *boy;TPerson *girl;
private slots:void do_ageChanged(int value);void do_spinChanged(int arg1);void on_growAYearBoy_clicked();void on_growAYearGirl_clicked();void on_pushButton_4_clicked();void on_showMetaInfo_clicked();void on_showMetaInfoGirl_clicked();
};
#endif // WIDGET_H

        widget.cpp:

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);boy = new TPerson("傲天",this);girl = new TPerson("夙玉",this);//动态属性定义boy->setProperty("sex", "boy");girl->setProperty("sex", "girl");boy->setAge(15);girl->setAge(20);ui->spinBoxBoy->setProperty("isBoy", true);ui->spinBoxGirl->setProperty("isBoy", false);connect(boy, SIGNAL(ageChanged(int)), ui->spinBoxBoy, SLOT(setValue(int)));connect(girl, SIGNAL(ageChanged(int)), ui->spinBoxGirl, SLOT(setValue(int)));connect(boy, SIGNAL(ageChanged(int)), this, SLOT(do_ageChanged(int)));connect(girl, SIGNAL(ageChanged(int)), this, SLOT(do_ageChanged(int)));connect(ui->spinBoxBoy, SIGNAL(valueChanged(int)), this, SLOT(do_spinChanged(int)));connect(ui->spinBoxGirl, SIGNAL(valueChanged(int)), this, SLOT(do_spinChanged(int)));
}Widget::~Widget()
{delete ui;
}void Widget::do_ageChanged(int value)
{//先用sender查看信号的发送者TPerson *person = qobject_cast<TPerson *>(sender());//获取年龄并打印到ptext中QString str = QString("name:%1,sex=%2,年龄=%3").arg(person->property("name").toString()).arg(person->property("sex").toString()).arg(value);ui->plainTextEdit->appendPlainText(str);
}void Widget::do_spinChanged(int arg1)
{
//    Q_UNUSED(arg1)QSpinBox *spBox = qobject_cast<QSpinBox*>(sender());//这里的sender指信号的发送者,在connect函数中,sender肯定是一个QSpinBox对象if(spBox->property("isBoy").toBool())boy->setAge(arg1);elsegirl->setAge(arg1);
}void Widget::on_growAYearBoy_clicked()
{boy->increaseAge();
}void Widget::on_growAYearGirl_clicked()
{girl->increaseAge();
}void Widget::on_pushButton_4_clicked()
{ui->plainTextEdit->clear();
}void Widget::on_showMetaInfo_clicked()
{const QMetaObject *meta = boy->metaObject();ui->plainTextEdit->appendPlainText(QString("类名称:%1\n").arg(meta->className()));ui->plainTextEdit->appendPlainText("属性:");for(int i=meta->propertyOffset();i<meta->propertyCount();i++){const char* propName = meta->property(i).name();QString propValue = boy->property(propName).toString();ui->plainTextEdit->appendPlainText(QString("属性名称=%1,属性值=%2").arg(propName).arg(propValue));}ui->plainTextEdit->appendPlainText("\n类信息(classInfo):");for(int i=meta->classInfoOffset();i<meta->classInfoCount();i++){QMetaClassInfo classInfo = meta->classInfo(i);ui->plainTextEdit->appendPlainText(QString("Name=%1,Value=%2").arg(classInfo.name()).arg(classInfo.value()));}
}void Widget::on_showMetaInfoGirl_clicked()
{const QMetaObject *meta = girl->metaObject();ui->plainTextEdit->appendPlainText(QString("类名称:%1\n").arg(meta->className()));ui->plainTextEdit->appendPlainText("属性:");for(int i=meta->propertyOffset();i<meta->propertyCount();i++){const char* propName = meta->property(i).name();QString propValue = girl->property(propName).toString();ui->plainTextEdit->appendPlainText(QString("属性名称=%1,属性值=%2").arg(propName).arg(propValue));}ui->plainTextEdit->appendPlainText("\n类信息(classInfo):");for(int i=meta->classInfoOffset();i<meta->classInfoCount();i++){QMetaClassInfo classInfo = meta->classInfo(i);ui->plainTextEdit->appendPlainText(QString("Name=%1,Value=%2").arg(classInfo.name()).arg(classInfo.value()));}
}

        界面展示:

 

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

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

相关文章

npm发布包

1.npm 登录 在控制台输入命令 npm login 按提示输入用户名&#xff0c;密码&#xff0c;邮箱后登录 如果出现如下提示 需要将淘宝镜像源切换为npm源&#xff0c;删除或注释以下内容就行 2.发布 进入准备发布的代码的根目录下&#xff0c;输入命令 npm publish 3.删除已发…

3d虚拟vr汽车实景展厅吸引更多潜在消费者

随着人们对生活品质的追求&#xff0c;越来越多的消费者开始关注汽车的外观设计、内饰配置等方面。传统的展示方式已经不能满足消费者的需求&#xff0c;车辆VR虚拟漫游展示应运而生。借助VR虚拟现实和web3d开发建模技术&#xff0c;对汽车的外观、造型及信息数据进行数字化处理…

了解国家电网

参考网站&#xff1a; https://www.dlzstp.com 参考网站&#xff1a; https://zhuanlan.zhihu.com/p/99743123 中国电网分为国家电网和南方电网两个大型电网集团&#xff0c;南方电网管理广东、广西、海南、云南、贵州5省电网&#xff0c;国网管理除这5个省外的26个省市、市…

如何用DHTMLX组件为Web应用创建甘特图?(二)

dhtmlxGantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。甘特图仍然是项目管理应用程序中最需要的工具之一&#xff0c;DHTMLX Gantt组件提供了能提升研发甘特图功能所需的重要工具。 在这篇…

【数据结构】“单链表”的练习题

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

vue使用FullCalendar插件实现日历会议预约功能

目录 1. vue 项目使用npm安装插件 2. vue 页面代码&#xff08;直接复制粘贴可用&#xff09; 3. vue FullCalendar的内置函数以及配置 前言&#xff1a;此案例是用FullCalendar插件做一个会议日程预约功能&#xff0c;此功能可查看自己的日程安排会议信息等...... FullC…

【ChatGPT 指令大全】怎么使用ChatGPT写履历和通过面试

目录 怎么使用ChatGPT写履历 寻求履历的反馈 为履历加上量化数据 把经历修精简 为不同公司客制化撰写履历 怎么使用ChatGPT通过面试 汇整面试题目 给予回馈 提供追问的问题 用 STAR 原则回答面试问题 感谢面试官的 email 总结 在职场竞争激烈的今天&#xff0c;写一…

安卓4G核心板开发板_MTK6785/MT6785(Helio G95)安卓手机主板方案

联发科MTK6785&#xff08;Helio G95&#xff09;安卓核心板采用八核 CPU 具有两个强大的 Arm Cortex-A76 处理器内核&#xff0c;主频高达 2.05GHz&#xff0c;外加六个 Cortex-A55 高效处理器。其强大的图形性能由 Arm Mali-G76 MC4 提供&#xff0c;速度可提升至 900MHz 。 …

Java 之LocalDateTime的介绍和使用

LocalDateTime是Java的日期和时间类之一&#xff0c;用于表示不带时区信息的日期时间。 LocalDateTime 没有时区&#xff0c; 所以也就不能用来直接获取时间戳LocalDateTime 是一个基于值得类&#xff0c; 所以该类的示例不是通过构造函数的方式进行创建 以下是一些关于Loca…

07. Docker网络通信模式

目录 1、前言 2、基本原理 3、Docker网络配置 3.1、查看网络配置 3.2、4种网络模式 3.3、bridge模式 3.3.1、使用bridge网络 3.3.2、自定义bridge网络 3.4、host模式 3.5、container模式 3.6、none模式 4、小结 1、前言 前面我们介绍了Docker容器的相关内容&#…

GaussDB数据库的元数据及其管理简介

目录 一、前言 二、元数据简介 1、元数据定义 2、元数据分类 3、数据库元数据管理 三、GaussDB数据库的元数据管理 1、GaussDB数据库的元数据管理 2、通过“SQL 系统表/系统视图/系统函数”的方式管理&#xff08;采集&#xff09;元数据 1&#xff09;获取表、视图及…

【雷达通信】非相干多视处理(CSA)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Kubernetes高可用集群二进制部署(三)部署api-server

Kubernetes概述 使用kubeadm快速部署一个k8s集群 Kubernetes高可用集群二进制部署&#xff08;一&#xff09;主机准备和负载均衡器安装 Kubernetes高可用集群二进制部署&#xff08;二&#xff09;ETCD集群部署 Kubernetes高可用集群二进制部署&#xff08;三&#xff09;部署…

vue2-v-if和v-for的优先级是什么?

1、v-if和v-for的区别 作用&#xff1a; v-if指令用于条件性地渲染一块内容&#xff0c;这块内容只会在指令的表达式返回true值的时候被渲染。 v-for指令基于一个数组来渲染一个列表&#xff0c;v-for指令需要使用item in items 形式的特殊语法&#xff0c;其中&#xff0c;it…

性能测试怎么做?测试工具怎么选择?

在当前软件测试行业&#xff0c;熟练掌握性能测试已经是测试工程师们面试的敲门砖了&#xff0c;当然还有很多测试朋友们每天的工作更多的是点点点&#xff0c;性能方面可能也只是做过简单的并发测试&#xff0c;对于编写脚本&#xff0c;搭建环境方面也比较陌生。今天这篇文章…

vue3搭建(vite+create-vue)

目录 前提条件 输入命令 对于Add an End-to-End Testing Solution nightwatch和Cypress 和 Playwright 运行 前提条件 熟悉命令行已安装 16.0 或更高版本的 Node.js &#xff08;node -v查看版本&#xff09; 输入命令 npm init vuelatest 这一指令将会安装并执行 create-…

NVIDIA 535.86.05 Linux 图形驱动程序改进 Wayland 支持

导读NVIDIA公司近日发布了适用于 Linux、FreeBSD 和 Solaris 系统的 NVIDIA 535.86.05 图形驱动程序&#xff0c;作为其生产分支的维护更新&#xff0c;解决了各种错误和问题。 NVIDIA 535.86.05 是在 NVIDIA 535.54.03 发布一个多月之后发布的&#xff0c;它通过解决在使用某…

PSO粒子群优化算法

PSO粒子群优化算法 算法思想matlab代码python代码 算法思想 粒子群算法&#xff08;Particle Swarm Optimization&#xff09; 优点: 1&#xff09;原理比较简单&#xff0c;实现容易&#xff0c;参数少。 缺点: 1&#xff09;易早熟收敛至局部最优、迭代后期收敛速度慢的…

linux 文件的权限

修改文件的权限 我这里有一个test.txt 文件&#xff0c;我们ll 查看一下该文件相应的属性信息 其中&#xff0c;权限的位置是相对固定的即&#xff1a; 第一个位置是r 权限&#xff0c;代表可读权限。 第二个位置是w权限&#xff0c;代表可修改权限。 第三个位置是x权限&…

SSL 证书过期巡检脚本 (Python 版)

哈喽大家好&#xff0c;我是咸鱼 之前写了个 shell 版本的 SSL 证书过期巡检脚本 &#xff08;文章&#xff1a;《SSL 证书过期巡检脚本》&#xff09;&#xff0c;后台反响还是很不错的 那么今天咸鱼给大家介绍一下 python 版本的 SSL 证书过期巡检脚本 &#xff08;完整代码…