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