一、属性的定义
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