請(qǐng)尊重原創(chuàng)作品和譯文。轉(zhuǎn)載請(qǐng)保持文章完整性,并以超鏈接形式注明原始作者地址http://blog.csdn.net/changsheng230,方便其他朋友提問和指正。
剛開始接觸Qt的朋友可能對(duì)Qt在使用當(dāng)中需要聲明的各色各樣的宏感到神秘而又陌生,本文將介紹Qt中經(jīng)常使用的幾個(gè)宏: 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所有宏中最為重要的一個(gè),Q_OBJECT是使用信號(hào)槽機(jī)制以及其他所有元對(duì)象系統(tǒng)提供的服務(wù)(內(nèi)省、invokeMethod,元對(duì)象property系統(tǒng)等等)的前提條件。有關(guān)Q_OBJECT的討論請(qǐng)參考Qt源碼分析之QObject。
SIGNAL與SLOT
這兩個(gè)宏是調(diào)用connect方法時(shí)用到:
- 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;
- }
原來它會(huì)基于把我們定義的信號(hào)、槽的名稱返回一個(gè)字符串,比如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是Qt 4.1引入的,它們用來替換關(guān)鍵字signals和slots,原因是更好的與第三方信號(hào)槽機(jī)制兼容,比如boost庫。盡管Q_SIGNALS 與 Q_SLOTS看起來沒有做什么。其實(shí)不然,QT的元對(duì)象編譯器moc會(huì)識(shí)別聲明在頭文件中的宏Q_SIGNALS,Q_SLOTS。并做為依據(jù),生成元對(duì)象模型數(shù)據(jù),詳見文中最后所示代碼實(shí)例
Q_EMIT
#define Q_EMIT #define emit
Q_EMIT用來替換關(guān)鍵字emit,原因也是更好的與第三方信號(hào)槽機(jī)制兼容,比如boost庫。
這里要注意,我們看到Q_EMIT看起來同樣的簡單, 但它們是有區(qū)別的!表面的區(qū)別在于Q_SIGNALS 與 Q_SLOTS用在頭文件中,而Q_EMIT用在代碼視線中。 本質(zhì)的區(qū)別的在于,Q_SIGNALS 與 Q_SLOTS將被moc識(shí)別,是必須使用的。而Q_EMIT或者emit是可有可無的。它不會(huì)被moc識(shí)別,它存在的唯一理由是:增加代碼的可讀性。 也就是說如下代碼都能正常工作,但2)的寫法也許會(huì)惹怒你的同事。
- void method()
- {
- 1) emit signalA();
- 2) signalA();
- }
Q_INVOKABLE
#define Q_INVOKABLE
使用Q_INVOKABLE來修飾成員函數(shù),目的在于被修飾的成員函數(shù)能夠被元對(duì)象系統(tǒng)所喚起。這一機(jī)制在Qt C++/QML混合編程,Qt service framework, 以及Qt/ HTML5混合編程里廣泛使用。我會(huì)隨后另撰寫一文做深入探討。
Q_PROPERTY
#define Q_PROPERTY(text)
使用Q_PROPERTY用以聲明屬性,屬性類似于成員變量,但它能夠被元對(duì)象系統(tǒng)所訪問。QML的屬性便是利用該機(jī)制得以實(shí)現(xiàn)的。 Q_PROPERTY的用法如下:
Q_PROPERTY(QString title READ title WRITE setTitle USER true)
接下來,讓我們結(jié)合代碼來看一下上述宏的使用以及元對(duì)象編譯器是如何利用這些宏的。
- #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;
- };
以下代碼由元對(duì)象編譯器moc根據(jù)上述頭文件自動(dòng)生成:
- static const uint qt_meta_data_EllipseItem[] = {
-
- 5,
- 0,
- 0, 0,
- 5, 14,
- 1, 39,
- 0, 0,
- 0, 0,
- 0,
- 2,
-
- 13, 12, 12, 12, 0x05,
- 28, 12, 12, 12, 0x05,
-
- 36, 12, 12, 12, 0x0a,
- 43, 12, 12, 12, 0x0a,
-
- 57, 12, 50, 12, 0x02,
-
- 71, 50, 0x43495103,
-
- 0,
- 0
- };
- static const char qt_meta_stringdata_EllipseItem[] = {
- "EllipseItem/0/0colorChanged()/0ready()/0"
- "try1()/0try2()/0QColor/0randomColor()/0"
- "color/0"
- };
從上面代碼實(shí)例我們可以看到, QT的元對(duì)象編譯器moc會(huì)識(shí)別聲明在頭文件中的宏Q_SIGNALS,Q_SLOTS, Q_PROPERTY, Q_PROPERTY。并以此做為依據(jù),生成了元對(duì)象數(shù)據(jù)表。在這張?jiān)獙?duì)象數(shù)據(jù)表中,我們已可以看到,moc根據(jù)頭文件所聲明的宏定義,識(shí)別出:
- 兩個(gè)信號(hào):colorChanged(), ready(); (Q_SIGNALS)
- 兩個(gè)槽: try1(), try2() (Q_SLOTS)
- 五個(gè)方法,其中被標(biāo)記為Q_INVOKABLE的方法randomColor()被記錄在元對(duì)象字符串?dāng)?shù)組qt_meta_stringdata_EllipseItem中。
- 一個(gè)屬性:color (Q_PROPERTY)