C++ Qt屬性零碎詳細引見。本站提示廣大學習愛好者:(C++ Qt屬性零碎詳細引見)文章只能為提供參考,不一定能成為您想要的結果。以下是C++ Qt屬性零碎詳細引見正文
C++ Qt屬性零碎詳細引見
Qt提供了一個絕妙的屬性零碎。跟那些由編譯器提供的屬性差不多。但是,作為一個獨立於編譯器戰爭台的庫,Qt不依賴於非規范的編譯特性,比方__property 或[property]。Qt可以在任何平台上的規范編譯器下編譯。Qt屬性零碎基於元數據對象零碎--就是那個提供了對象內相信號和槽通訊機制的家伙。
聲明屬性需求什麼
要聲明一個屬性,需在承繼自QObject的類中運用Q_PROPERTY()宏。
Q_PROPERTY(type name READ getFunction [WRITE setFunction] [RESET resetFunction] [NOTIFY notifySignal] [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] [USER bool] [CONSTANT] [FINAL])
上面是一些典型的聲明屬性的示例:
Q_PROPERTY(bool focus READ hasFocus) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)一個屬性的行為好像類的數據成員,但是它還具有附加的特性,這些特性可以被元數據對象零碎操作。這些特性是:需求一個READ訪問器函數。用於讀屬性的值。理想狀況下,有一個不變的函數用於此目的,並且它必需前往屬性的類型的值或指針或援用。例如,QWidget::focus是一個只讀的屬性,它對應一個讀函數:QWidget::hasFocus()。 一個可選的WRITE訪問器函數。它用於設置屬性的值。它必需前往空並且至多具有一個參數,參數是屬性類型的值或指針或援用。例如:QWidget::enabled具有WRITE函數QWidget::setEnable()。只讀屬性不需求寫函數。例如,QWidget::focus沒有對應的寫函數。 一個可選的RESET函數。用於設置屬性的值到它的默許值。例如:QWidget::cursor具有典型的READ和WRITE函數,QWidget::cursor()和QWidget::setCursor(),並且它也具有一個RESET函數,QWidget::unsetCursor()。RESET函數必需前往void並且不帶有任何參數。 一個可選的NOTIFY信號。假如被定義了,信號將在屬性的值改動時收回。信號必需帶有一個參數,這個參數的類型必需與屬性相反;參數保管的是屬性的新值。 一個DESIGNABLE變量標明此屬性能否在界面設計器的屬性編輯器中呈現。大少數屬性是可見的,除了為這個變量傳入true或false,你還可以指定一個bool型的成員函數。 SCRIPTABLE變量標明這個屬性能否可以被一個腳本引擎操作(默許是true)。你也可以賦予它true或false或bool型函數。 STORED變量標明了屬性能否被以為是獨立存在還是依賴於其它的值而存在。它也標明能否在保管對象形態時保管此屬性的值。大少數屬性都是需求保管的,但是,如QWidget::minimumWidth()就是不被保管的,由於它的值是從另一個屬性QWidget::minimumSize()得來的。 USER變量標明屬性能否被設計為面向用戶的或用戶可修正的類屬性。通常,每個類只要一個USER屬性。例如,QAbstractButton::checked是按鈕類的用戶可修正屬性。留意QItemDelegate獲取和設置widget的USER屬性。 CONSTANT的呈現標明屬性的值是不變的。關於一個object實例,常量屬性的READ辦法在每次被調用時必需前往相反的值。此常量值能夠在不同的object實例中不相反。一個常量屬性不能具有WRITE辦法或NOYIFY信號。 FINAL變量的呈現標明屬性不能被派生類所重寫。有些狀況下,這可以用於效率優化,但不是被moc強迫的。順序員必需永遠留意不能重寫一個FINAL屬性。
READ,WRITE和RESET函數都可以被承繼。它們也可以是虛函數。當它們在被多重承繼中被承繼時,它們必需呈現在第一個被承繼的類中。
屬性的類型可以是被QVariant支持的一切類型,也可以是用戶定義的類型。在上面的例子中,類QDate被當作用戶自定義類型。
Q_PROPERTY(QDate data READ getDate WRITE setDate)
由於QDate是用戶定義的,你必需包括<QDate>頭文件。
關於QMap,QList和QValueList屬性,屬性的值是一個QVariant,它包括整個list或map。留意Q_PROPERTY字符串不能包括逗號,由於逗號會劃分宏的參數。因而,你必需運用QMap作為屬性的類型而不是QMap<QString,QVariant>。為了堅持分歧性,也需求用QList和QValueList而不是QList<QVariant>和QValueList<QVariant>。
經過元數據對象零碎讀寫屬性
一個屬性可以運用慣例函數QObject::property()和QObject::setProperty()停止讀寫,不必知道屬性所在類的任何細節,除了屬性的名字。在上面的小代碼片段中,調用QAbstractButton::setDown()和QObject::setProperty()都把屬性設置為“down”。
QPushButton *button = new QPushButton; QObject *object = button; button->setDown(true); object->setProperty("down", true);
經過WRITE操作器來操作一個屬性是下面兩者中更好的,由於它快並且在編譯時給於更好的診斷協助,但是以這種方式設置屬性要求你必需在編譯時理解其類。經過名字來操作屬性使你可以操作在編譯器你不理解的類。你可以在運轉時發現一個類的屬性們,經過查詢它的QObject,QMetaObject和QMetaProerties。
QObject *object = ... const QMetaObject *metaobject = object->metaObject(); int count = metaobject->propertyCount(); for (int i=0; i<count; ++i) { QMetaProperty metaproperty = metaobject->property(i); const char *name = metaproperty.name(); QVariant value = object->property(name); ... }
在下面的代碼片段中,QMetaObject::property()被用於獲取未知類中的屬性的metadata。從metadata中獲取屬性名然後傳給QObject::property()來獲取
一個復雜例子
假定我們有一個類MyClass,它從QObject派生並且在它的private區運用 了Q_OBJECT宏。我們想在MyClass類中聲明一個屬性來繼續追蹤一個Priorty值。屬性的值叫做priority,並且它的類型是一個在類MyClass中定義的叫做Priority的枚舉。
我們在類的private區運用Q_PROPERTY()來聲明屬性。READ函數叫做priority,並且我們包括一個WRITE函數叫做setPriority。枚舉類型必需運用Q_ENUMS()注冊到元數據對象零碎中。注冊一個枚舉類型使得枚舉的名字可以在調用QObject::setProperty()時運用。我們還必需為READ和WRITE函數提供我們自己的聲明。MyClass的聲明看起來應該是這樣的:
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()聲明的靜態類型中,也可以被用於靜態類型中。
感激閱讀,希望能協助到大家,謝謝大家對本站的支持!