天天看點

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;

}

繼續閱讀