QT信號槽鏈接

 

MOC

一:信號槽是什麼? html

Qt的信號和槽機制是Qt的一大特色,實際上這是和MFC中的消息映射機制類似的東西,要完成的事情也差很少,就是發送一個消息而後讓其它窗口響應,固然,這裏的消息是廣義的說法,簡單點說就是如何在一個類的一個函數中觸發另外一個類的另外一個函數調用,並且還要把相關的參數傳遞過去.好像這和回調函數也有點關係,可是消息機制可比回調函數有用 數組

 

二:Qt支持三種類型的信號-槽鏈接:
1,直接鏈接,當signal發射時,slot當即調用。此slot在發射signal的那個線程中被執行(不必定是接收對象生存的那個線程)
2,隊列鏈接,當控制權回到對象屬於的那個線程的事件循環時,slot被調用。此slot在接收對象生存的那個線程中被執行
3,自動鏈接(缺省),假如信號發射與接收者在同一個線程中,其行爲如直接鏈接,不然,其行爲如隊列鏈接。
鏈接類型可能經過以向connect()傳遞參數來指定。注意的是,當發送者與接收者生存在不一樣的線程中,而事件循環正運行於接收者的線程中,使用直接鏈接是不安全的。一樣的道理,調用生存在不一樣的線程中的對象的函數也是否是安全的。QObject::connect()自己是線程安全的。 安全

用Qt寫Gui程序的時候,在main函數裏面最後依據都是app.exec();不少書上對這句的解釋是,使Qt程序進入消息循環。   app

當前connectionType爲Qt::AutoConnection而且signal和slot不在一個線程或者是signal和再也不當前線程中;或者是c->connectionType爲 Qt::QueuedConnection這時候調用函數queued_activate:對參數轉換一下,而後調用QCoreApplication::postEvent
注意: postEvent第二個參數是QMetaCallEvent。
這樣這個signal-slot的connection就發送到receiver的消息隊列中去了。  函數

 

三:connect(sender,SIGNAL(signal()),receiver,SLOT(slot())); 
這裏用到了兩個宏:SIGNAL() 和SLOT();經過connect聲明能夠知道這兩個宏最後卻是獲得一個const char*類型
在qobjectdefs.h中能夠看到SIGNAL() 和SLOT()的宏定義: 工具

#ifndef QT_NO_DEBUG 
# define QLOCATION "\0"__FILE__":"QTOSTRING(__LINE__) 
# define METHOD(a)   qFlagLocation("0"#a QLOCATION) 
# define SLOT(a)     qFlagLocation("1"#a QLOCATION) 
# define SIGNAL(a)   qFlagLocation("2"#a QLOCATION) 
#else 
# define METHOD(a)   "0"#a 
# define SLOT(a)     "1"#a 
# define SIGNAL(a)   "2"#a 
#endif 
因此這兩個宏的做用就是把函數名轉換爲字符串而且在前面加上標識符post

好比:SIGNAL(read())展開後就是"2read()";同理SLOT(read())展開後就是"1read()"。 ui

connect(sender,SIGNAL(signal()),receiver,SLOT(slot())); 
實際上就是connect(sender,「2signal()」,receiver,「1slot())」;  .net

 

四: 線程

# if defined(QT_NO_KEYWORDS)
#  define QT_NO_EMIT
# else
#   define slots
#   define signals protected
# endif
# define Q_SLOTS
# define Q_SIGNALS protected
# define Q_PRIVATE_SLOT(d, signature)
# define Q_EMIT
#ifndef QT_NO_EMIT
# define emit
#endif

signals宏有點不一樣,它限定Qt信號爲protected方法,而slots宏能夠是任意類型。

頭文件定義的public slots和signals對C++編譯器而言沒有意義,會被替換成public和protected。他們的真實意圖實際上是給moc工具使用的,moc根據這些字符串關鍵字匹配,用來生成文件moc_Counter.cppQt源碼的構建過程是先moc轉換而後再執行C++編譯器。moc的目的是展開信號和槽,生成一個能讓編譯器讀懂的源文件

 

五:MOC元數據

Q_OBJECT建立QMetaObejct元對象數據成員:用來作信號槽的二維表。對於某一個信號,在二維表中存放着這個信號對應的槽的函數指針。依據這個信號的名字去查詢二維表,找到對應的槽的函數指針並進行調用

 

Qt的信號槽機制其實就是按照名稱查表,所以這裏的首要問題是如何構造這個表?和C++虛函數表機制相似的,在Qt中,這個表就是元數據表

不過Qt彷佛尚未徹底發揮元數據的能力,動態屬性,反射之類的機制

通常是經過宏Q_OBJECT定義的(內省函數
#define Q_OBJECT / 
public: / 
    static const QMetaObject staticMetaObject; / 
    virtual const QMetaObject *metaObject() const; / 
    virtual void *qt_metacast(const char *); / 
    QT_TR_FUNCTIONS / 
    virtual int qt_metacall(QMetaObject::Call, int, void **); / 
private: 

這裏的三個虛函數metaObject,qt_metacast,qt_metacall是在moc文件中定義的
staticMetaObject是 QMetaObject對象,由於須要給屬於同一類的所有實例共享,因此它是靜態的。獲得元數據表指針
metaObject方法僅僅返回staticMetaObject。
QT_TR_FUNCTIONS是一個用於全部tr函數的宏,用來實現多語言支持。
qt_metacast用於按照類名或它的某個基類名 進行動態轉換(dynamic cast)【Qt顯然不依賴運行時類型檢查(RTTI)】。
qt_metacall經過索引查表調用內部信號和槽參數由一個指向指針數組的指針進行傳遞,並在調用方法時進行適當的轉換

 

用戶設計的類能夠從多個類派生,但只能擁有一個QObject(或從它派生)基類,這同時也是超類
class ConvDialog : public QDialog, private Ui::ConvDialog
{
    Q_OBJECT
Moc將產生如下代碼:
const QMetaObject ConvDialog::staticMetaObject = {
    { &QDialog::staticMetaObject, qt_meta_stringdata_ConvDialog,
      qt_meta_data_ConvDialog, 0 }
};
若是在QDialog前先繼承Ui::ConvDialog,moc將會生成:
const QMetaObject ConvDialog::staticMetaObject = {
    { &Ui::ConvDialog::staticMetaObject, qt_meta_stringdata_ConvDialog,
      qt_meta_data_ConvDialog, 0 }
};
這是錯誤的,由於Ui::ConvDialog不是QObject的一個派生類,由此不擁有staticMetaObject成員,這樣作只會致使一個編譯錯誤。

 

QMetaObject中的結構體d

struct{
        const QMetaObject *superdata;//這是元數據表明的類的基類的元數據
        const char *stringdata;//這是元數據的簽名標記
        const uint *data;//這是元數據的索引數組的指針
        const QMetaObject **extradata;//這是擴展元數據表的指針,通常是不用的 
}d;


第一個參數:QMetaObject類指針,指向父Qt元數據類。

第三個參數:無符號整型數組,這個數組是一個表,包含全部元數據的偏移、特徵等等。因此,若是你想枚舉一個類的信號和槽,那就應該遍歷這個表,經過偏移量從stringdata數組中得到方法名。

 

 

參考文章:http://blog.csdn.net/tingsking18/article/details/4991563

http://www.cnblogs.com/findumars/p/4851262.html

http://www.pediy.com/kssd/pediy12/133181.html

http://www.devbean.net/2012/12/how-qt-signals-and-slots-work/

相關文章
相關標籤/搜索