亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++ Qt屬性系統詳細介紹

2020-05-23 13:58:22
字體:
來源:轉載
供稿:網友

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()聲明的靜態類型中,也可以被用于動態類型中。

 感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情综合色综合啪啪五月| 欧美韩国理论所午夜片917电影| 欧美高清视频在线观看| 曰本色欧美视频在线| 亚洲第一综合天堂另类专| 亚洲一区二区三区成人在线视频精品| 久国内精品在线| 久久深夜福利免费观看| 亚洲aⅴ日韩av电影在线观看| 精品少妇v888av| 久久亚洲成人精品| 影音先锋欧美在线资源| 久久中国妇女中文字幕| 成人444kkkk在线观看| 日韩成人中文字幕在线观看| 狠狠躁天天躁日日躁欧美| 欧美精品精品精品精品免费| 欧美成人免费在线视频| 亚洲福利视频在线| 91精品国产乱码久久久久久蜜臀| 国产偷国产偷亚洲清高网站| 精品二区三区线观看| 97人洗澡人人免费公开视频碰碰碰| 在线播放日韩精品| 亚洲视频999| 岛国av一区二区| 亚洲毛片一区二区| 亚洲美女动态图120秒| 91av中文字幕| 日韩有码在线观看| 黑人精品xxx一区一二区| 亚洲人成电影网站色www| 欧美色另类天堂2015| 川上优av一区二区线观看| 色午夜这里只有精品| 视频一区视频二区国产精品| 亚洲欧美三级在线| 日韩成人av网址| 亚洲一级一级97网| 97人人爽人人喊人人模波多| 国产va免费精品高清在线观看| 成人中心免费视频| 亚洲美女视频网站| 亚洲精品日韩久久久| 国产一区二区三区毛片| 欧美黄色成人网| 亚洲精品视频免费在线观看| 最近的2019中文字幕免费一页| 成人免费视频网| 欧美猛交免费看| 久久久久久久97| 欧美在线一区二区视频| 欧美日韩午夜剧场| 亚洲欧美www| 55夜色66夜色国产精品视频| 欧美精品videos性欧美| 国产欧美亚洲视频| 麻豆乱码国产一区二区三区| 亚洲精品欧美极品| 国产美女扒开尿口久久久| 欧美电影院免费观看| 九九视频直播综合网| 日韩成人激情在线| 国产精品久久久久久久久久东京| 国产一区二区丝袜高跟鞋图片| 亚洲影视中文字幕| 久久手机精品视频| 91精品国产色综合| 亚洲国产美女久久久久| 欧美激情高清视频| 成人h视频在线观看播放| 日韩成人激情影院| 欧美日韩亚洲一区二区三区| 欧美日韩在线看| 国产精品久久久久久久久久三级| 久久综合国产精品台湾中文娱乐网| 国产日韩在线一区| 亚洲午夜精品久久久久久性色| 国产精品日韩欧美综合| 色播久久人人爽人人爽人人片视av| 热久久美女精品天天吊色| 欧美专区在线观看| 欧美日韩在线视频观看| 欧美日韩在线看| 国产一区二区三区网站| 国产精品电影网| 国产999精品久久久影片官网| 日韩av大片免费看| 久久久久国产精品免费| 久久久国产精彩视频美女艺术照福利| 国产精品综合网站| 国产精品女人久久久久久| 成人免费大片黄在线播放| 国产视频久久网| 国产亚洲xxx| 亚洲欧洲国产精品| 久久精品电影网站| 精品国产拍在线观看| 欧美激情视频网址| 日本精品免费一区二区三区| 欧美亚洲激情视频| 国产欧美日韩丝袜精品一区| 综合136福利视频在线| 色999日韩欧美国产| 国产精品中文字幕久久久| 69视频在线免费观看| 国内精品美女av在线播放| 日韩经典第一页| 久久精品成人欧美大片| 久久综合色88| 国产精品人成电影| 日韩av电影在线免费播放| 色偷偷888欧美精品久久久| 亚洲国产精品久久| 国产精品视频一区国模私拍| 久久6精品影院| 在线中文字幕日韩| 色yeye香蕉凹凸一区二区av| 日本精品一区二区三区在线播放视频| 国产精品亚洲网站| 精品亚洲男同gayvideo网站| 欧美另类老肥妇| 色偷偷偷综合中文字幕;dd| 国产成人福利视频| 久久久国产精品免费| 色综合91久久精品中文字幕| 日韩精品视频在线观看免费| 日韩电影免费观看在线观看| 亚洲精品在线看| 一区国产精品视频| 成人欧美一区二区三区黑人孕妇| 国产精品第3页| 中文字幕日韩精品在线观看| 日韩欧美国产视频| 亚洲精品视频免费在线观看| 亚洲欧洲午夜一线一品| 国产亚洲aⅴaaaaaa毛片| 欧美精品性视频| 久久久亚洲精品视频| 亚洲午夜av电影| 成人字幕网zmw| 亚洲影院色在线观看免费| 国产专区精品视频| 1769国产精品| 伊人久久久久久久久久久久久| 亚洲一区二区三区四区在线播放| 6080yy精品一区二区三区| 粉嫩av一区二区三区免费野| 成人啪啪免费看| 国产亚洲精品成人av久久ww| 欧美精品一本久久男人的天堂| 欧美激情一区二区三区高清视频| 2019中文字幕在线| 国产精品久久久久久av福利| 久久中文字幕国产| 97视频免费看| 亚洲人成自拍网站| 精品国产网站地址| 欧美人与物videos| 欧美成人合集magnet| 97在线看福利| 在线观看国产欧美| 中文字幕日韩欧美在线| 92看片淫黄大片看国产片|