1. 静态属性(Static Properties)
1.1 基本概念
静态属性是指编译时候就已经确定的属性,通常是通过Q_PROPERTY宏声明。运行时可以通过元对象系统访问和操作。
1.2 使用方法
声明静态属性:
class MyClass : public QObject {
Q_OBJECT
Q_PROPERTY(int myProperty READ myProperty WRITE setMyProperty NOTIFY myPropertyChanged)
/*int 属性类型
* myProperty 属性名
* READ 读
* myProperty 读方法
* WRITE 可选
* setMyProperty 设置属性的方法,可选
* NOTIFY 可选 后面跟这个中已经定义好的一个信号函数,调用setMyProperty的时候,在这个函数中,当这个属性的值发生改变就手动会发出这个信号。
* 这个信号函数必须采用零个或者一个参数,这个参数必须和属性的类型一致
* myPropertyChanged可选 指定的信号
*/
public:
MyClass(QObject *parent = nullptr) : QObject(parent), m_myProperty(0) {}
int myProperty() const { return m_myProperty; }
void setMyProperty(int value) {
if (m_myProperty != value) {
m_myProperty = value;
emit myPropertyChanged();
}
}
signals:
void myPropertyChanged();
private:
int m_myProperty;
};
访问静态属性:
方式1:通过元对象访问:metaObject->property() metaObject->propertyOffset()
方式2:直接通过Q_PROPERTY声明的get/set方法访问
//测试静态属性
void demoStaticProperty()
{
Property proper;
//通过 set方法设置属性
proper.setGender(Property::Female);
qDebug()<<"访问方式1 Gender:"<<proper.gender();
// 访问元信息
// 元对象系统:通过metaObject访问属性的元信息,包括属性名称、类型和值。
// 遍历属性:使用QMetaObject::propertyCount 和 QMetaObject::property
// 遍历所有属性,并打印其名称、类型和值
const QMetaObject *metaObject = proper.metaObject();
int start = metaObject->propertyOffset();//获取用户定义属性的起始索引
for (int i = start; i < metaObject->propertyCount(); ++i)
{
QMetaProperty metaProperty = metaObject->property(i);
qDebug() << "访问方式2 Property Name:" << metaProperty.name();
qDebug() << "Property Type:" << metaProperty.typeName();
qDebug() << "Property Value:" << metaProperty.read(&proper);
}
qDebug()<<"访问方式3 gender:"<<proper.property("gender").toInt();
//通过属性名设置值
proper.setProperty("gender",Property::Other);
qDebug()<<"NEW gender:"<<proper.gender();
}
1.3 应用场景
数据绑定:静态属性可以与Qt的信号和槽机制结合,实现数据绑定。
数据绑定通常是指将一个数据源(如一个变量的值)与一个或者多个用户界面元素(如控件的属性)绑起来,当数据源发生变化的术后,用户界面元素的属性会自动更新。
样式表定制:静态属性可以用于样式表中,根据属性值应用不同的样式。
this->setProperty("customstyle",true);//设置静态属性
//应用样式表 使用样式表setStyleSheet根据customStyle属性的值应用不同的样式。
setStyleSheet("StaticProperty[customstyle=true] { background-color: red; }");
元信息访问:通过元对象系统访问属性的元信息,如类型、名称等。
// 访问元信息
/*元对象系统:通过metaObject访问属性的元信息,包括属性名称、类型和值。
遍历属性:使用QMetaObject::propertyCount 和 QMetaObject::property
遍历所有属性,并打印其名称、类型和值。*/
const QMetaObject *metaObject = widget.metaObject();
for (int i = 0; i < metaObject->propertyCount(); ++i) {
QMetaProperty metaProperty = metaObject->property(i);
qDebug() << "Property Name:" << metaProperty.name();
qDebug() << "Property Type:" << metaProperty.typeName();
qDebug() << "Property Value:" << metaProperty.read(&widget);
}
1.4 注意事项
静态属性需要在类中声明,并且需要提供读取和写入方法。
静态属性支持信号通知,当属性值改变时可以发出信号。
2. 动态属性(Dynamic Properties)
2.1 基本概念
动态属性是运行时动态添加到对象的属性。
它们不需要在类定义中声明,可以动态地添加、修改和删除。
2.2 使用方法
设置动态属性:
//setProperty(const QString &name,const QVariant &value)
obj.setProperty("dynamicProperty", "value");
获取动态属性:
//property(const QString &name)const
qDebug() << obj.property("dynamicProperty").toString();
检查动态属性是否存在:
if (obj.dynamicPropertyNames().contains("dynamicProperty")) {
qDebug() << "Dynamic property exists.";
}
2.3 应用场景
运行时扩展对象属性:动态属性适合在运行时根据需要添加属性。
样式表QSS使用自定义属性:动态属性可以用于样式表中,根据属性值应用不同的样式。
临时存储与对象相关的数据:动态属性可用于管理对象的运行时状态。
2.4 注意事项
动态属性的值是QVariant类型,需要确保类型正确性。
动态属性的性能开销比静态属性略高,因为它涉及到运行时的查找。
3. 静态属性与动态属性的区别
静态属性 | 动态属性 |
---|---|
编译时(通过宏声明) | 不需要预先声明,运行时(动态添加) |
需要moc (Q_OBJECT) | 不需要(直接调用) |
通过getter/setter访问 | 通过property()/setProperty()访问 |
支持 NOTIFY 信号 | 不支持信号通知 |
性能更快(编译优化) | 性能稍慢(运行时查找) |
编译时检查 | 编译时不进行类型检查,运行时检查(QVariant) |
总结
Q_PROPERTY 声明的是静态属性,需要编译时定义,但更高效、功能更完整(支持信号、QML 绑定等)。
动态属性 (setProperty) 是运行时的,灵活但功能有限(无信号、类型不安全)。动态属性查找比静态属性慢,适合少量、不频繁访问的属性
优先用 Q_PROPERTY(性能、类型安全、信号支持)。
仅在需要运行时扩展时用动态属性(如临时存储、QSS 条件样式)。