深度解析 Qt Quick 宏
Qt Quick 宏是本篇所介紹的內(nèi)容。剛開始接觸Qt的朋友可能對Qt在使用當(dāng)中需要聲明的各色各樣的宏感到神秘而又陌生,本文將介紹Qt中經(jīng)常使用的幾個宏: Q_OBJECT, SIGNAL與SLOT, Q_SIGNALS 與 Q_SLOTS, Q_EMIT ,Q_INVOKABLE, Q_PROPERTY:
宏的頭文件出處: $QTDIR\src\corelib\kernel\qobjectdefs.h
- Q_OBJECT
 - #define Q_OBJECT \
 - public: \
 - Q_OBJECT_CHECK \
 - static const QMetaObject staticMetaObject; \
 - Q_OBJECT_GETSTATICMETAOBJECT \
 - virtual const QMetaObject *metaObject() const; \
 - virtual void *qt_metacast(const char *); \
 - QT_TR_FUNCTIONS \
 - virtual int qt_metacall(QMetaObject::Call, int, void **); \
 
宏Q_OBJECT是Qt所有宏中最為重要的一個,Q_OBJECT是使用信號槽機制以及其他所有元對象系統(tǒng)提供的服務(wù)(內(nèi)省、invokeMethod,元對象property系統(tǒng)等等)的前提條件。有關(guān)Q_OBJECT的討論請參考Qt源碼分析之QObject。
SIGNAL與SLOT
這兩個宏是調(diào)用connect方法時用到:
- QObject::connect(myButton, SIGNAL(clicked()),
 - label, SLOT(showText()));
 - QObject::connect(myButton, SIGNAL(clicked()),
 - label, SLOT(showText()));
 
那么宏SIGNAL和SLOT為我們做了那些事情呢,看一下源代碼:
- $QTDIR\src\corelib\kernel\qobjectdefs.h
 - # define SLOT(a) qFlagLocation("1"#a QLOCATION)
 - # define SIGNAL(a) qFlagLocation("2"#a QLOCATION)
 - $QTDIR\src\corelib\kernel\qobject.cpp
 - const char *qFlagLocation(const char *method)
 - {
 - static int idx = 0;
 - flagged_locations[idx] = method;
 - idx = (idx+1) % flagged_locations_count;
 - return method;
 - }
 - $QTDIR\src\corelib\kernel\qobjectdefs.h
 - # define SLOT(a) qFlagLocation("1"#a QLOCATION)
 - # define SIGNAL(a) qFlagLocation("2"#a QLOCATION)
 - $QTDIR\src\corelib\kernel\qobject.cpp
 - const char *qFlagLocation(const char *method)
 - {
 - static int idx = 0;
 - flagged_locations[idx] = method;
 - idx = (idx+1) % flagged_locations_count;
 - return method;
 - }
 
原來它會基于把我們定義的信號、槽的名稱返回一個字符串,比如SIGNAL(clicked()) 返回字符串 “2clicked()”, SLOT(showText())返回字符串“1showText()”
- Q_SIGNALS 與 Q_SLOTS
 - # define slots
 - # define signals protected
 - # define Q_SLOTS
 - # define Q_SIGNALS protected
 - Q_SIGNALS 與 Q_SLOTS
 - # define slots
 - # define signals protected
 - # define Q_SLOTS
 - # define Q_SIGNALS protected
 
Q_SIGNALS 與 Q_SLOTS是Qt 4.1引入的,它們用來替換關(guān)鍵字signals和slots,原因是更好的與第三方信號槽機制兼容,比如boost庫。盡管Q_SIGNALS 與 Q_SLOTS看起來沒有做什么。其實不然,QT的元對象編譯器moc會識別聲明在頭文件中的宏Q_SIGNALS,Q_SLOTS。并做為依據(jù),生成元對象模型數(shù)據(jù),詳見文中***所示代碼實例
- Q_EMIT
 - #define Q_EMIT
 
#define emitQ_EMIT用來替換關(guān)鍵字emit,原因也是更好的與第三方信號槽機制兼容,比如boost庫。
這里要注意,我們看到Q_EMIT看起來同樣的簡單, 但它們是有區(qū)別的!表面的區(qū)別在于Q_SIGNALS 與 Q_SLOTS用在頭文件中,而Q_EMIT用在代碼視線中。 本質(zhì)的區(qū)別的在于,Q_SIGNALS 與 Q_SLOTS將被moc識別,是必須使用的。而Q_EMIT或者emit是可有可無的。它不會被moc識別,它存在的唯一理由是:增加代碼的可讀性。 也就是說如下代碼都能正常工作,但2)的寫法也許會惹怒你的同事。
- void method()
 - {
 - 1) emit signalA();
 - 2) signalA();
 - }
 - void method()
 - {
 - 1) emit signalA();
 - 2) signalA();
 - }
 - Q_INVOKABLE
 - #define Q_INVOKABLE
 
使用Q_INVOKABLE來修飾成員函數(shù),目的在于被修飾的成員函數(shù)能夠被元對象系統(tǒng)所喚起。這一機制在Qt C++/QML混合編程,Qt service framework, 以及Qt/ HTML5混合編程里廣泛使用。我會隨后另撰寫一文做深入探討。
- Q_PROPERTY
 - #define Q_PROPERTY(text)
 
使用Q_PROPERTY用以聲明屬性,屬性類似于成員變量,但它能夠被元對象系統(tǒng)所訪問。QML的屬性便是利用該機制得以實現(xiàn)的。 Q_PROPERTY的用法如下:
- Q_PROPERTY(QString title READ title WRITE setTitle USER true)
 
接下來,讓我們結(jié)合代碼來看一下上述宏的使用以及元對象編譯器是如何利用這些宏的。
- #include <QDeclarativeItem >
 - class EllipseItem : public QDeclarativeItem
 - {
 - Q_OBJECT
 - Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
 - public:
 - EllipseItem(QDeclarativeItem *parent = 0);
 - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
 - QWidget *widget = 0);
 - const QColor &color() const;
 - void setColor(const QColor &newColor);
 - Q_INVOKABLE QColor randomColor() const;
 - public Q_SLOTS:
 - void try1();
 - void try2() {}
 - Q_SIGNALS:
 - void colorChanged();
 - void ready();
 - private:
 - QColor m_color;
 - };
 - #include <QDeclarativeItem >
 - class EllipseItem : public QDeclarativeItem
 - {
 - Q_OBJECT
 - Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
 - public:
 - EllipseItem(QDeclarativeItem *parent = 0);
 - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
 - QWidget *widget = 0);
 - const QColor &color() const;
 - void setColor(const QColor &newColor);
 - Q_INVOKABLE QColor randomColor() const;
 - public Q_SLOTS:
 - void try1();
 - void try2() {}
 - Q_SIGNALS:
 - void colorChanged();
 - void ready();
 - private:
 - QColor m_color;
 - };
 
以下代碼由元對象編譯器moc根據(jù)上述頭文件自動生成:
- static const uint qt_meta_data_EllipseItem[] = {
 - // content:
 - 5, // revision
 - 0, // classname
 - 0, 0, // classinfo
 - 5, 14, // methods
 - 1, 39, // properties
 - 0, 0, // enums/sets
 - 0, 0, // constructors
 - 0, // flags
 - 2, // signalCount
 - // signals: signature, parameters, type, tag, flags
 - 13, 12, 12, 12, 0x05,
 - 28, 12, 12, 12, 0x05,
 - // slots: signature, parameters, type, tag, flags
 - 36, 12, 12, 12, 0x0a,
 - 43, 12, 12, 12, 0x0a,
 - // methods: signature, parameters, type, tag, flags
 - 57, 12, 50, 12, 0x02,
 - // properties: name, type, flags
 - 71, 50, 0x43495103,
 - // properties: notify_signal_id
 - 0,
 - 0 // eod
 - };
 - static const char qt_meta_stringdata_EllipseItem[] = {
 - "EllipseItem\0\0colorChanged()\0ready()\0"
 - "try1()\0try2()\0QColor\0randomColor()\0"
 - "color\0"
 - };
 - static const uint qt_meta_data_EllipseItem[] = {
 - // content:
 - 5, // revision
 - 0, // classname
 - 0, 0, // classinfo
 - 5, 14, // methods
 - 1, 39, // properties
 - 0, 0, // enums/sets
 - 0, 0, // constructors
 - 0, // flags
 - 2, // signalCount
 - // signals: signature, parameters, type, tag, flags
 - 13, 12, 12, 12, 0x05,
 - 28, 12, 12, 12, 0x05,
 - // slots: signature, parameters, type, tag, flags
 - 36, 12, 12, 12, 0x0a,
 - 43, 12, 12, 12, 0x0a,
 - // methods: signature, parameters, type, tag, flags
 - 57, 12, 50, 12, 0x02,
 - // properties: name, type, flags
 - 71, 50, 0x43495103,
 - // properties: notify_signal_id
 - 0,
 - 0 // eod
 - };
 - static const char qt_meta_stringdata_EllipseItem[] = {
 - "EllipseItem\0\0colorChanged()\0ready()\0"
 - "try1()\0try2()\0QColor\0randomColor()\0"
 - "color\0"
 - };
 
從上面代碼實例我們可以看到, QT的元對象編譯器moc會識別聲明在頭文件中的宏Q_SIGNALS,Q_SLOTS, Q_PROPERTY, Q_PROPERTY。并以此做為依據(jù),生成了元對象數(shù)據(jù)表。在這張元對象數(shù)據(jù)表中,我們已可以看到,moc根據(jù)頭文件所聲明的宏定義,識別出:
兩個信號:colorChanged(), ready(); (Q_SIGNALS)
兩個槽: try1(), try2() (Q_SLOTS)
五個方法,其中被標(biāo)記為Q_INVOKABLE的方法randomColor()被記錄在元對象字符串?dāng)?shù)組qt_meta_stringdata_EllipseItem中。
一個屬性:color (Q_PROPERTY)
原始作者地址http://blog.csdn.net/changsheng230
小結(jié):關(guān)于深度解析 Qt Quick宏淺議的內(nèi)容介紹完了,希望本文對你有所幫助!















 
 
 
 
 
 
 