Qt之自定義屬性Q_PROPERTY


 Qt提供了一個絕妙的屬性系統。跟那些由編譯器提供的屬性差不多。然而,作為一個獨立於編譯器和平台的庫,Qt不依賴於非標准的編譯特性,比如__property 或[property]。Qt可以在任何平台上的標准編譯器下編譯。Qt屬性系統基於元數據對象系統--就是那個提供了對象內置信號和槽通訊機制的家伙。

    Q_PROPERTY()是一個宏,用來在一個類中聲明一個屬性property,由於該宏是qt特有的,需要用moc進行編譯,故必須繼承於QObject類。

 

Q_PROPERTY(type name
   READ getFunction
   [WRITE setFunction]
   [RESET resetFunction] [NOTIFY notifySignal] [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] [USER bool] [CONSTANT] [FINAL])

下面是一些典型的聲明屬性的示例:

 

 

Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue) Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation) Q_PROPERTY(QColor barColor READ getBarColor WRITE setBarColor)

 

 

  • 一個屬性的行為就像類的數據成員,但是它還具有附加的特性,這些特性可以被元數據對象系統操作。這些特性是:
    需要一個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>。

代碼調用的例子:

 

class Test : public QObject { Q_OBJECT Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) public: Test(QObject *parent = 0) : QObject(parent) {} virtual ~Test(){} void setEnabled(bool e) { enabled = e; } bool isEnabled() const { return enabled; } private: bool enabled; }; 

然后在主函數中添加:

 

 

Test *test = new Test; test->setProperty("enabled", true); //test->setEnabled(true); //ok also work if(test->property("enabled").toBool()) ..... 


Qt Creator Designer插件的 例子:

 

頭文件中定義了一個minValue 的屬性,如下:

 

class BarRuler : public QWidget { Q_OBJECT Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue) public: explicit BarRuler(QWidget *parent = 0); ~BarRuler(); private: double minValue; public: double getMinValue() const; public slots: void setRange(double minValue, double maxValue); };


cpp文件實現如下:

 

 

#include "barruler.h" BarRuler::BarRuler(QWidget *parent) : QWidget(parent) { minValue = 0; } BarRuler::~BarRuler() { } double BarRuler::getMinValue() const { return this->minValue; } void BarRuler::setMinValue(double minValue) { this->minValue = minValue; update(); } 


在設計模式界面調用如下:

 

1、先拖入一個widget控件

2、在其上右鍵選擇“提升為”BarRuler

3、點擊屬性欄的加號,選擇其它類型,如圖

4、類型和名稱都要和頭文件里定義的相同,如圖

5、在屬性欄就會出現對應的動態屬性,如圖

6、修改數值,就會改變相對應定義的屬性了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM