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()));}
}
界面展示:

相关文章:
QT属性系统
1 介绍 Qt中的属性系统是用于为对象添加自定义属性并管理这些属性的一种机制。它允许开发者在不修改类定义的情况下,动态地为Qt对象添加新的属性,并且能够对这些属性进行读取、设置和监听。 属性系统在Qt中是通过Q_PROPERTY宏和QObject的元对象系统来实现…...
CentOS 7虚拟机 虚拟机安装安装增强VBox_GAs_6.1.22失败:modprobe vboxguest failed
我安装的CentOS 在安装增强工具的时候报错: 查阅资料后 ,解决方法: 1、更新kernel内核版本: yum update kernel -y //安装kernel-devel和gcc编译工具链yum install -y kernel-devel gcc//更新kernel和kernel-devel到最新版本yum -y upgrade …...
【基础类】—DOM事件系统性学习
一、基本概念:DOM事件的级别 // DOM0 element.onclickfunction(){} // DOM2, 新增了冒泡和捕获 element.addEventListener(click,function(){}, false) // DOM3, 新增更多事件类型 鼠标、键盘等 element.addEventListener(keyup,function(){}, false)二、DOM事件模…...
【控制项目风险经验之谈】
项目风险是指在项目执行期间可能会影响项目目标、进度、成本或质量的不确定因素。在项目管理中,项目风险是不可避免的,因此需要采取措施来控制和管理项目风险。本篇文章将详细介绍如何控制项目风险的经验之谈。 一、确定风险管理计划 在项目启动阶段&a…...
SpringBoot复习:(10)SpringApplication中的initializer成员变量是怎么初始化的?
initializers成员变量定义如下: 在构造方法里通过setInitializers setInitializers的代码很简单: 其中的参数通过getSpringFactoriesInstances来获取的,该方法的代码如下: 其中调用的重载的方法代码如下: 它调用…...
Java三大特征之继承【超详细】
文章目录 一、继承概念二、继承的语法三、父类成员访问3.1子类中访问父类的成员变量3.2子类和父类成员变量同名3.3子类中访问父类的成员方法 四、super关键字五、子类构造方法六、super和this七、再谈初始化八、protected 关键字九、继承方式十、final 关键字十一、继承与组合 …...
python: lidar点云转BEV投影及pillar/voxel
点云BEV投影及pillar体素化 bev投影pillar/voxel bev投影 点云bev投影代码 pillar/voxel #!/usr/bin/env python # -*- encoding: utf-8 -*-import os import numpy as np import mathn_max_points_per_pillar 32 n_max_pillars 20736 # 144*144 20736 n_in_features 7…...
我的创作纪念日2023.8.5
机缘 在CSDN的创作开始于去年,创作的初衷是希望对自己的学习经历进行记录,同时也把自己的经验和收获传递给更多需要的小伙伴。创作博客的过程是一个将输入的知识进行再生产的过程,在此期间,知识获得了沉淀和提纯,思路…...
课程作业-基于Python实现的迷宫搜索游戏附源码
简单介绍一下 该项目不过是一个平平无奇的小作业,基于python3.8开发,目前提供两种迷宫生成算法与三种迷宫求解算法,希望对大家的学习有所帮助。 项目如果有后续的跟进将会声明,目前就这样吧~ 效果图如下所示: 环境…...
差值结构的相互作用能
( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点,AB训练集各由6张二值化的图片组成,让A,B中各有3个点,且不重合,统计迭代次数并排序。 其中有10组数据 差值结构 A-B 迭代次数 构造平均列 平均列…...
UI、UE、UX的区别
UI、UE、UX的区别 大部分程序员可能对UI、UE、UX这几个概念不是很熟悉,但在整个项目周期里,这些岗位还是很重要的,特别是对于产品公司,这些岗位对于一个产品是否能成功起着关键的作用。老规矩,我们先看看这三个缩写的定义。 UI:是User Interface英文的缩写,即用户界面的…...
RabbitMQ 教程 | 第10章 网络分区
👨🏻💻 热爱摄影的程序员 👨🏻🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…...
Flask学习笔记_异步论坛(四)
Flask学习笔记_异步论坛(四) 1.配置和数据库链接1.exts.py里面实例化sqlalchemy数据库2.config.py配置app和数据库信息3.app.py导入exts和config并初始化到app上 2.创建用户模型并映射到数据库1.models/auth.py创建用户模型2.app.py导入模型并用flask-mi…...
K8S系列文章之 kubeasz部署K8S环境
自动化安装方式(kubeasz)* 生产环境推荐(首次安装下载相关配置和安装包)是基于Ansible实现的部署工具 简单介绍 每一具体k8s集群的详细配置参数文件 Ansible 任务配置文件 镜像安装包 安装部署步骤 前提 : 保证Ansib…...
nodejs和vue的关系--vue3教程
文章目录 总结性nodejs和vue的关系nodejs和vue产生关系的周边nodejs和vue的区别 总结性 vue是一套用于构建用户界面的前端框架,如果web项目中有前后端分离,前端项目想单独运行在服务器端,那么就要依赖nodeJs。 Vue的配套周边会和Node.js产生…...
前端大屏尺寸实现自适应屏幕大小
说在前面 目前很多业主在使用系统的时候都会有大屏的需求,很多屏幕并不会像我们开发的屏幕一样标准,比如1920*1080,这样我们就需要根据业主的屏幕尺寸进行适配,避免一些图表或文字在大屏中出现偏移,影响视觉观感。 方…...
leetcode 416. 分割等和子集
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 输入:nums [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。 示例 2&a…...
cesium加载三维模型3dtiles
1.将数据和代码放到一个目录下 目的:为避免跨域 输入cmd命令 python3 -m http.server 5500 2.三维服务地址 http://127.0.0.1:5500/data/mars3d-max-shihua-3dtiles-master/tileset.json 3.模型网页地址 http://127.0.0.1:5500/cesium/cesium%E5%8A%A0%E8%BD%…...
el-select控制单选还是多选
<el-form :inline"true" :model"form" class"demo-form-inline"><el-form-item><el-select v-model"form.properties_id" placeholder"请选择样品性质" clearable :multiple"multiple_properties"…...
nginx使用
1 安装 yum -y install gcc pcre-devel zlib-devel openssl openssl-devel yum install -y wget wget https://nginx.org/download/nginx-1.16.1.tar.gz tar -zxvf nginx-1.16.1.tar.gz cd nginx-1.16.1 ./configure --prefix/usr/local/nginx make make install2 目录 目录说…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
