首页 > 其他分享 >Qt之属性系统

Qt之属性系统

时间:2023-10-01 10:36:33浏览次数:42  
标签:PROPERTY Qt int age 系统 Person 属性 name

一、属性的定义

1.赋予属性读写操作

Qt提供了一个Q_PROPERTY()宏可以定义属性,它也是基于元对象系统实现的,在QObject的子类中,用Q_PROPERTY()定义属性。

QWidget类兴义属性的一些例子:

Q_PROPERTY(bool focus READ hasFocus)
Q_PROPERTY(bool enable READ isEnable WRITE setEnable)
Q_PROPERTY(QCursor cursor READ WRITE setCursor RESET unsetCursor)

Q_PROPERTY(bool focus READ hasFocus):定义了一个focurs属性,指明了它是bool类型,而且需要用自定义的hasFocus()函数来读取这个属性值。

Q_PROPERTY(bool enable READ isEnable WRITE setEnable):定义了一个enable属性,指明了它是bool类型,需要使用自定的isEnable()函数读取这个属性值,通过setEnable()函数来修改属性值。 

Q_PROPERTY(QCursor cursor READ WRITE setCursor RESET unsetCursor):定义了一个cursor属性,指明了它是QCursor 类型,需要使用自定的setCursor()函数来修改属性值,通过unsetCursor()函数来进行默认值设置。

2.将类的成员变量导出为一个属性值

上述所说的属性值并不是QWidget的成员变量,如果想要将QWidget类中的某个变量导出一个属性值,需要使用关键字MEMBER将变量注册到Qt的属性系统中。

如下所示:

class Person : public QObject 
{ Q_OBJECT Q_PROPERTY(QString name MEMBER m_name) private: QString m_name; };

上述代码中把Person类中的私有成员变量m_name导出为一个属性值,并且命名为name,那么从外界访问时能识别到的的属性值只有name而不是m_name。

3.Q_PROPERTY的常用格式

我们声明的属性值,常用的操作无非就是读、写、将成员变量导出为属性值、关联信号等。

class Person : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChaned)
    Q_PROPERTY(QString name MEMBER m_name)
public:
    explicit Person(QString name, QObject *parent = nullptr);
    int age();
    void setAge(int value);
signals: void ageChaned(int value);
private: int m_age; QString m_name; };

例如上述代码中:

  • 使用age这个属性值,用READ关键字指定获取属性值的函数为age(),用WRITE关键指定修改属性值的函数为setAge()。
  • 上述的age这个属性值并不是类中的成员变量,是凭空声明出来的一个属性值,如果想要将类中已有的成员变量设置为属性值,需要使用关键字MEMBER,如代码中的属性name关联着m_name,修改属性值name时,m_name的值也会随之改变。
  • 给属性值设置关联信号,如果我们希望某个属性值变化时能够发出信号,Qt的属性系统是用关键字NOTIFY来指定信号。

二、属性的使用

不管是否使用了READ和WRITE定义了接口函数,只要知道属性名称,就可以通过QObject:property()读取属性值,并通过QObject::setProperty()设置属性值

例如:

QPushButton *pButton = new QPushButton(this);
pButton->setProperty("flat", QVariant(true));
bool bFlat = pButton->property("flat").toBool();

1.动态属性

  • 动态属性是在运行时动态添加到对象上的属性,而不需要在编译时声明或定义。
  • 你可以使用 QObject 类的 setProperty 方法来为对象添加动态属性,这个方法接受属性名和属性值作为参数。
  • 动态属性对于自定义属性非常有用,因为它们允许你在不修改类定义的情况下为对象添加自定义信息。
  • 动态属性通常用于个别对象实例,而不是整个类。

2.静态属性:

  • 静态属性是在编译时静态定义的属性,它们通常在类定义中使用 Q_PROPERTY 宏来声明。
  • 静态属性的声明通常伴随着属性的读取和写入方法的定义,以及属性的默认值等信息。
  • 静态属性通常用于整个类,而不是单个对象实例。这意味着所有该类的对象共享相同的属性。

下面示例演示了动态属性和静态属性的区别:

class MyObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString staticProperty READ getStaticProperty)
    
public:
    QString getStaticProperty() const { return m_staticProperty; }
    
private:
    QString m_staticProperty = "Static Property Value";
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    MyObject object1;
    object1.setProperty("dynamicProperty", "Dynamic Property Value"); // 添加动态属性

    QString dynamicValue = object1.property("dynamicProperty").toString(); // 读取动态属性值
    QString staticValue = object1.getStaticProperty(); // 读取静态属性值

    qDebug() << "Dynamic Property:" << dynamicValue; // 输出动态属性值
    qDebug() << "Static Property:" << staticValue; // 输出静态属性值
    
    return app.exec();
}

在这个示例中,dynamicProperty 是一个动态属性,可以在运行时添加。staticProperty 是一个静态属性,通过 Q_PROPERTY 宏在类定义中声明。

总的来说,动态属性用于为对象添加自定义属性,而静态属性用于在类级别定义属性,通常伴随着属性的读取和写入方法。

3.类的附加信息

属性系统还有一个宏Q_CLASSINFO(),可以为类的元对象定义"名称-值"信息,如下所示:

class Person : public QObject
{
    Q_OBJECT
    Q_CLASSINFO("author", "Wang")
    Q_CLASSINFO("company", "UPC")
    Q_CLASSINFO("version", "1.0.0")
public:
     ... 
};

用Q_CLASSINFO()宏定义附加类信息后,可以通过元对象的一些函数获取类的附件信息,如calssInfo(int)获取某个附加信息。

函数原型定义如下:  

QMetaClassInfo QMteaObject::classInfo(int index) const

返回值是QMetaClassInfo类型,有name()和value两个函数,可获得类附加信息的名称和值。

示例代码如下:

Person *pBoy = new Person();
const QMetaObject* metaObject = pBoy->metaObject();
int infoCount = metaObject->classInfoCount();

for (int i = 0; i < infoCount; ++i) {
       QMetaClassInfo info = metaObject->classInfo(i);
       qDebug() << "Key:" << info.name() << ", Value:" << info.value();
}

打印信息:

4.在不知道类的属性情况下获取属性的值

Person *pBoy = new Person("王小明");
const QMetaObject *metaobject = pBoy->metaObject();
int count = metaobject->propertyCount();

for (int i = 0; i < count; ++i) {
    QMetaProperty metaproperty = metaobject->property(i);
    const char *name = metaproperty.name();
    QVariant value = pBoy->property(name);
} 

三、完整代码示例

头文件:

#ifndef PERSON_H
#define PERSON_H

#include <QObject>

class Person : public QObject
{
    Q_OBJECT
    Q_CLASSINFO("author", "Wang")
    Q_CLASSINFO("company", "UPC")
    Q_CLASSINFO("version", "1.0.0")
    Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChaned)
    Q_PROPERTY(QString name MEMBER m_name)
    Q_PROPERTY(int score MEMBER m_score)
public:
    explicit Person(QString name, QObject *parent = nullptr);
    int age();
    void setAge(int value);
    void incAge();

signals:
    void ageChaned(int value);

private:
    int m_age;
    QString m_name;
    int m_score;
};

#endif // PERSON_H

源文件:

#include "person.h"

Person::Person(QString name, QObject *parent) : QObject(parent)
{
    m_name = name;
}

int Person::age()
{
    return  m_age;
}

void Person::setAge(int value)
{
    m_age = value;

    emit ageChaned(m_age);
}

void Person::incAge()
{
    m_age++;
    emit ageChaned(m_age);
}

属性调用:  

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
{
    m_pBoy = new Person("王小明");
    connect(m_pBoy, &Person::ageChaned, this, &MainWindow::on_ageChanged);

    m_pBoy->setProperty("socre", QVariant(95));
    m_pBoy->setProperty("sex", QVariant("Boy")); //动态属性
    m_pBoy->setProperty("age", QVariant(10));
}

MainWindow::~MainWindow()
{
}

void MainWindow::on_ageChanged(int value)
{
    Q_UNUSED(value);

    Person *pPserson = qobject_cast<Person*>(sender()); //类型投射
    QString name = pPserson->property("name").toString();
    QString sex = pPserson->property("sex").toString();
    //int age = pPserson->property("age").toInt();//通过属性获取年龄
    int age = pPserson->age(); //通过接口函数获取年龄
    qDebug() << name + "," + sex + "," + QString::asprintf("年龄=%d", age);
}

打印信息: 

  

标签:PROPERTY,Qt,int,age,系统,Person,属性,name
From: https://www.cnblogs.com/TechNomad/p/17738626.html

相关文章

  • 信息安全系统设计与实现课程第七、八章学习笔记
    一、知识点归纳1.1、文件操作级别文件操作分为五个级别,按照从低到高的顺序排列如下:(1)硬件级别:硬件级别的文件操作包括:fdisk:用于将硬盘、U盘或SD卡等存储设备分区。mkfs:用于格式化磁盘分区,为文件系统做好准备。fsck:用于检查和维修文件系统的一致性。碎片整理:用于压缩......
  • 《信息安全系统设计与实现》第四周学习笔记
    《信息安全系统设计与实现》第四周学习笔记第七章:文件操作文件操作级别硬件级别fdisk:将硬盘、U盘或SDC盘分区mkfs:格式化磁盘分区,为系统做好准备fsck:检查和维修系统碎片整理:压缩文件系统中的文件操作系统内核中的文件系统函数每个操作系统内核均可为基本文件操作提供......
  • pyqt-核心布局
    1、直接启动or选择启动一些应用是基于同一个目录下的配置加载,以及日志写入同一目录。而另一些应用是根据目标或时间等分为不同的配置目录与日志目录。对于前者,那么自然的是启动程序,进行读取和加载。而后者可以是启动后读取加载上一状态,也可以是先进入开始窗口,选择新建或其它。2......
  • SpringBoot框架大晚上报错404--我的路径问题(附上SpringBoot MVC管理系统的简单具体代
    代码application.ymlspring:web:resources:static-locations:classpath:/static/,classpath:/templates/datasource:type:com.alibaba.druid.pool.DruidDataSourceurl:jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=utf......
  • 线性系统与信号(三):采样、信号、状态空间分析
    连续时间信号分析①周期信号:傅里叶级数  连续时间信号分析②非周期信号:傅里叶积分  采样:从连续到离散的过渡  离散时间信号的傅里叶分析  状态空间分析......
  • 线性系统与信号:MATLAB课时11节
    MATLAB课时B:初步操作  MATLAB课时1:使用函数  MATLAB课时2:M文件  MATLAB课时3:离散时间信号与系统  MATLAB课时4:连续时间滤波器  MATLAB课时5:离散时间IIR滤波器  MATLAB课时6:傅里叶级数应用   MATLAB课时7:傅里叶变换   MATLAB课时8:离散......
  • 【中秋国庆不断更】OpenHarmony定义可动画属性:@AnimatableExtend装饰器
    【中秋国庆不断更】OpenHarmony定义可动画属性:@AnimatableExtend装饰器@AnimatableExtend装饰器用于自定义可动画的属性方法,在这个属性方法中修改组件不可动画的属性。在动画执行过程时,通过逐帧回调函数修改不可动画属性值,让不可动画属性也能实现动画效果。​●......
  • 2023-2024-1 20211327 信息安全系统设计与实现 学习笔记4(必做)
    学习笔记4文件操作使用系统调用进行文件操作实践过程文件操作1.文件操作级别(1)硬件级别:fdisk:将硬盘、U盘或SDC盘分区mkfs:格式化磁盘分区,为系统做好准备fsck:检查和维修系统碎片整理:压缩文件系统中的文件(2)操作系统内核中的文件系统函数:前缀k表示内核函数(3)系......
  • pyqt5-QSize尺寸类
    1、介绍QSize,pyqt中用于定义组件尺寸的类。在处理图片对象QIcon等时常用。QSize()QSize(w:int,h:int)QSize(a0:QSize)2、基础使用setHeight(self,h:int)height(self)->intsetWidth(self,w:int)width(self)->int设置高度、获取高度、设置宽度、获取宽度 ......
  • 【中秋国庆不断更】OpenHarmony定义可动画属性:@AnimatableExtend装饰器
    【中秋国庆不断更】OpenHarmony定义可动画属性:@AnimatableExtend装饰器@AnimatableExtend装饰器用于自定义可动画的属性方法,在这个属性方法中修改组件不可动画的属性。在动画执行过程时,通过逐帧回调函数修改不可动画属性值,让不可动画属性也能实现动画效果。​●......