天天看点

Qt属性setProperty & property [转载]

1.属性有什么用?

由于c++类具备封装特性,不推荐对类成员变量(class variables)进行直接存取。现代编译器引用属性(property)的概念,对成员变量进行安全的存取。比如在win平台下 vc7有类似于__property或[property]的支持。Qt由于要实现其跨平台(cross platform),引入一套独特的属性系统。其底层是由meta compiling进行支持。

2.格式

Q_PROPERTY(type name

READ getFunction

[WRITE setFunction]

[RESET resetFunction]

[DESIGNABLE bool]

[SCRIPTABLE bool]

[STORED bool])

* Q_PROPERTY: qt里定义的宏;

* type name: 即类型名+属性名,属性名(name)在QObject的setProperty里被引用;

* READ: 设置读取成员变量的函数名,一定要是const,可以返回void,Qvariant支持的对象,指针,或const的引用。READ是必须的,而write, reset等则是可选的;只有READ的属性为只读属性;

* WRITE: 写成员变量的函数名,返回值必须是void,可以设置一个参数,这个参数可以是void,QVaraint支持的变量,指针,或const的引用。可选;具备READ和WRITe的属性是可读写属性。

* DESIGNABLE: 指示该属性是否被图形编辑器(比如designer)使用。默认是TRUE;

* SCRIPTABLE: 指示是否在script里使用,Trolltech公司同时有基于Qt的QSA,用于在应用程序的脚本编程;默认是TRUE;

* STORED: 指示是否可被持久化(persistence)。只有WRITE被设定的时候,STORED才有效。默认是TRUE。

3. 使用

比有一个类,

class MyClass : public QObject

{

Q_OBJECT

public:

MyClass (QString f) {this->f =f;}

~MyClass() {}

//property begin

QString getF() const {return f;}

void setF(QString ff) {f=ff;}

//property end

private:

QString f;

};

这时在public之前定义property

Q_PROPERTY (QString F READ getF WRITE setF)

照惯例,读取函数往往省略get,即定义了

QString F() const {return f;}

这时,Q_PROPERTY (QString F READ F WRITE setF)

但实际上,读取、写、和重置(reset)函数可以是任何名字,比如前面用getF。

在使用时,属性跟一般的成员函数一样被使用,比如:

MyClass classA("initial");

QString out=classA.getF();

//out = "initial"

QString t="this is a test";

classA.setF(t);

//classA里的f现在是"this is a test"

此外,可以通过QObject::setProperty()和property()来使用属性,比如

MyClass classB("classB");

//这时的f是"classB"

classB.setProperty("F", "this is a test");

//这时调用setF("this is a test"),成员变量f现在是"this is a test"

使用setProperty可能效率比直接调用setF低,但注意到setProperty是基类的成员,所以通过QObject::property/setProperty可以遍历全部派生自QOjbect的类的属性。比如:

QObject* p = &classA;

p->setProperty("F", "test A");

p=&classB;

p->setProperty("F", "test B");

熟悉多态的朋友,马上就应该联想到这种机制的一些优越性。其中奥秘请看多类的相关描述,这里主要讲Qt的属性,不赘。

QObject::property/setProperty跟QMetaObject::propertyCount(),和QMetaObject::property()结合起来,可以实现动态的函数调用,类似于dotnet里的reflection机制。

4. 如果property的参数是enum,那么在定义Q_PROPERTY时,必须先告诉meta system使用的enum,使用宏Q_ENUMS,次序无关,如:

Q_PROPERTY(Priority priority READ priority WRITE setPriority)

Q_ENUMS(Priority)

其中Priority是枚举类型。

5.一个较为复杂的例子,使用了一个引用输入属性的写函数。请注意,此引用必须为const。

CaliforniaWhiteWine.h

#include <QObject>

class WhiteWine

{};

class CaliforniaWhiteWine :

public QObject

{

Q_OBJECT

Q_PROPERTY(WhiteWine& m_wine READ getWine WRITE setWine)

public:

CaliforniaWhiteWine();

CaliforniaWhiteWine(WhiteWine& wine);

~CaliforniaWhiteWine();

WhiteWine& getWine() const;

void setWine(const WhiteWine& wine)

{

delete m_wine;

*m_wine = wine;

}

protected:

WhiteWine* m_wine;

};

CaliforniaWhiteWine.cpp

#include ".\californiawhitewine.h"

CaliforniaWhiteWine::CaliforniaWhiteWine(void)

{

this->m_wine=new WhiteWine();

}

CaliforniaWhiteWine::~CaliforniaWhiteWine(void)

{

delete m_wine;

}

CaliforniaWhiteWine::CaliforniaWhiteWine(WhiteWine& wine)

{

}

WhiteWine& CaliforniaWhiteWine::getWine() const

{

return *m_wine;

}

继续阅读