C++ Qt属性系统详细介绍

2020-01-06 16:04:12王旭


class MyClass : public QObject 
{ 
  Q_OBJECT 
  Q_PROPERTY(Priority priority READ priority WRITE setPriority) 
  Q_ENUMS(Priority) 
public: 
  MyClass(QObject *parent = 0); 
  ~MyClass(); 
  enum Priority { High, Low, VeryHigh, VeryLow }; 
  void setPriority(Priority priority); 
  Priority priority() const; 
}; 

READ函数是const的并且返回属性的类型。WRITE函数返回void并且具有一个属性类型的参数。元数据对象编译器强制做这些事情。

在有了一个指向MyClass实例的指针时,我们有两种方法来设置priority属性:


MyClass *myinstance = new MyClass; 
 QObject *object = myinstance; 
 myinstance->setPriority(MyClass::VeryHigh); 
 object->setProperty("priority", "VeryHigh"); 

在此例子中,枚举类型在MyClass中声明并被使用Q_ENUMS()注册到元数据对象系统中。这使得枚举值可以在调用setProperty()时做为字符串使用。如果枚举类型是在其它类中声明的,那么我们就需要用枚举的全名(如OtherClass::Priority),并且这个其它类也必须从QObject中派生并且也要注册枚举类型。

另一个简单的Q_FLAGS()也是可用的。就像Q_ENUMS(),它注册一个枚举类型,但是它把枚举类型作为一个flag的集合,也就是,值可以用OR操作来合并。一个I/O类可能具有枚举值Read和Write并且QObject::setProperty()可以接受 Read|Write。此时应使用Q_FLAGS()来注册枚举值。

动态属性

Qobject::setProperty()也可以用来在运行时向一个类的实例添加新的属性。当使用一个名字和值调用它时,如果一个对应的属性已经存在,并且如果值的类型与属性的类型兼容,那么值就被存储到属性中,然后返回true。如果值类型不兼容,属性的值就不会发生改变,就会返回false。但是如果对应名字的属性不存在,那么一个新的属性就诞生了,以传入的名字为名,以传入的值为值,但是依然会返回false。这表示返回值不能用于确定一个属性是否被设置值,除非你已经知道这个属性已经存在于QObject中了。

注意动态属性被添加到单个实现的基础中,也就是,被添加到QObject,而不是QMetaObject。一个属性可以从一个实例中删除,通过传入属性的名字和非法的QVariant值给QObject::setProperty()。默认的QVariant构造器构造一个非法的QVariant。
动态属性可用QObject::property()来查询,就行使用Q_PROPERTY()声明的属性一样。

属性和自定义类型

被属性使用的自定义类型需要使用Q_DECLARE_METATYPE()宏注册,以使它们的值能被保存在QVariant对象中。这使得它们可以用于被Q_PROPERTY()声明的静态类型中,也可以被用于动态类型中。

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!