qt中实现息屏开平mousepress_QT信号槽分析
默認安裝好了VS2015 和QT
下載QT pdb和QT src壓縮包(選擇自己的版本,我是5.9.8)
qt下載網址
拷貝自己需要的文件,qt目錄中D:\Qt\Qt5.9.8\5.9.8我是這個
并且把源碼也拷貝進同一目錄,當然其他的目錄也行
設置VS選項
工具->選項->調試->符號
項目->xxxx屬性->vc++目錄(添加源碼路徑)
測試對著qt的函數或者宏按F12
安裝查看源碼的軟件(Source Insight)
這個工具可以很好的分析源碼
分析QT信號槽分析moc生成的文件
案例代碼
#include class QtClass : public QObject{ Q_OBJECTpublic: QtClass(QObject *parent); ~QtClass(); void Test(){ emit Sig1(5); }signals: void Sig1(int nVal); //void Sig2(bool b); //void Sig3(bool b); //void Sig4(bool b, int nVal); private slots: void Slot1(int nVal0){ qDebug() << nVal0; }}信號函數只有聲明,沒有實現?
emit Sig1(5);這句代碼調用信號,但是我們沒有實現信號這個函數呀。我們沒有實現,那么是什么能夠幫我們實現呢?當然是編譯器。
調試信號函數
F11發現是有實現代碼的吧
打開文件所在目錄
查看moc文件夾,分析編譯器都給我們生成了什么
定義了一個結構體
qt_meta_stringdata_QtClass_t
struct qt_meta_stringdata_QtClass_t { QByteArrayData data[6]; char stringdata0[31];};后面創建了一個結構體靜態變量里面存放一些類、參數、函數名等信息。這個第一個參數應該是ID,字符串的開始位置,字符串size
QT_MOC_LITERAL(0, 0, 7), // "QtClass"
static const qt_meta_stringdata_QtClass_t qt_meta_stringdata_QtClass = { {QT_MOC_LITERAL(0, 0, 7), // "QtClass" //類名QT_MOC_LITERAL(1, 8, 4), // "Sig1" //信號名QT_MOC_LITERAL(2, 13, 0), // "" QT_MOC_LITERAL(3, 14, 4), // "nVal" //參數名QT_MOC_LITERAL(4, 19, 5), // "Slot1" //槽函數名QT_MOC_LITERAL(5, 25, 5) // "nVal0" //槽參數名 }, "QtClass\0Sig1\0\0nVal\0Slot1\0nVal0"};qt_meta_data_QtClass : 存儲類中函數相關的信息
static const uint qt_meta_data_QtClass[] = { // content: 7, // revision //qt對應版本 0, // classname 0, 0, // classinfo 2, 14, // methods //2個函數 context長度14 0, 0, // properties 0, 0, // enums/sets 0, 0, // constructors 0, // flags 1, // signalCount //信號數量 // signals: name, argc, parameters, tag, flags 1, 1, 24, 2, 0x06 /* Public */,//name:對應qt_meta_stringdata_QtClass_t結構體的ID,是"Sig1"//argc:是參數個數//parameters:該函數的具體聲明在在qt_meta_data_QtClass結構體的偏移 // slots: name, argc, parameters, tag, flags 4, 1, 27, 2, 0x08 /* Private */,//上面的parameters就是指向這里// 返回值 參數1... 這個結構的大小24 // signals: parameters QMetaType::Void, QMetaType::Int, 3,27 // slots: parameters QMetaType::Void, QMetaType::Int, 5, 0 // eod};qt_static_metacall類的信號/槽函數調用的實現地址判斷傳進來的ID然后調用函數
void QtClass::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, { if (_c == QMetaObject::InvokeMetaMethod) { QtClass *_t = static_cast(_o); Q_UNUSED(_t) switch (_id) { case 0: _t->Sig1((*reinterpret_cast< int(*)>(_a[1]))); break; case 1: _t->Slot1((*reinterpret_cast< int(*)>(_a[1]))); break; default: ; } } else if (_c == QMetaObject::IndexOfMethod) { int *result = reinterpret_cast<int *>(_a[0]); { typedef void (QtClass::*_t)(int ); if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&QtClass:: *result = 0; return; } } }}staticMetaObject : 類信息的總和
紅色框是父類地址,藍色是存儲字符串的結構體的地址,黑色是存放信號槽函數信息的結構體,類的信號/槽函數調用的實現地址
metaObject:判斷靜態/動態調用
qt_metacast:返回類名稱
+qt_metacall:函數調用
void** _a:數組指針, 每個指針指向一個函數的地址
_c:實現函數的類型
_id : 函數id, 判斷是否實現 & 以何種方式實現該函數
信號函數的實現
void* _a[]是一個信號對應的槽函數的地址
一個信號可以對應多個槽,所有這里是void* _a[]數組
Q_OBJECT
從這里看是不是很明顯的能看出,這里寫了虛函數,然后生成moc文件幫我們實現
* qmake ignore Q_OBJECT */#define Q_OBJECT \ public: \ QT_WARNING_PUSH \ Q_OBJECT_NO_OVERRIDE_WARNING \ static const QMetaObject staticMetaObject; \ virtual const QMetaObject *metaObject() const; \ virtual void *qt_metacast(const char *); \ virtual int qt_metacall(QMetaObject::Call, int, void **); \ QT_TR_FUNCTIONS \ private: \ Q_OBJECT_NO_ATTRIBUTES_WARNING \ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, Q QT_WARNING_POP \ struct QPrivateSignal {}; \ QT_ANNOTATE_CLASS(qt_qobject, "")分析connect函數檢查函數
判斷參數是否為NULL
給Sender賦值獲取名字、對象、參數等
獲取sender的Index,并且判斷是否有效
接收方信息
判斷信號槽是否被關聯
判斷接收方是否有效可以被關聯
檢查發送者和接收者參數是否一致
執行關聯操作函數
進入實現函數
先是強轉了sender 和receiver保存在兩變量里面
檢測版本
估計是為了防止多線程,給了鎖
生成信號槽的對應關系Connection,并把Connection插入ConnectionList中
為對應的connect賦值
解鎖,并且檢查是否關聯成功
分析activate函數當我們發Sig1信號時調用的函數
紅框計算父類的信號
前面做了一系列檢查,是否還關聯著
構造一個ConnectListRef的結構體,類似ConnectList引用
這里用上面的Index找到關聯鏈表
遍歷表找到對應得connect
調用鏈表得槽函數
大體圖
end
總結
以上是生活随笔為你收集整理的qt中实现息屏开平mousepress_QT信号槽分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sqlite3 select查询一列_一
- 下一篇: c++ string 拼接_C++日志(