Qt的Signal和Slot機制 一

2021-07-04 08:47:16 字數 3459 閱讀 1951

最近在用qt開發專案,它的signal和slot機制引起了我的興趣,閒暇無聊,看了下源**,寫下了一些自己的心得。但其中難免有錯誤之處,望各位看官不吝指出。

第一節 signal和slot的鑰匙

我們知道qt 通過」connect」 函式,將乙個signal 和slot 對應了起來。為了形成對應,必有一結構來維護和儲存這個對應關係。這個結構就是我們的幕後英雄 qmetaobject 。一般我們只會在由qt 自動生成的moc 打頭的cpp 檔案裡看到。

它主要有以下三個變數,

const

qmetaobject *superdata ;

const

char *stringdata ;

const

uint *data ;

superdata 

,父類的qmetaobject 指標,當我們在本類找不到相應的signal 和slot 時,可以去父類中找。

換句話說,父類的signal 和slot ,子類一樣可以使用。

stringdata

,乙個字串,儲存了類名,signal ,slot 函式名,和他們的引數名字

data

,乙個陣列,從這個陣列中包含了「qmetaobjectprivate 「結構的資訊,signal 資訊,slot 資訊還有其他的諸如properties的資訊,signal 資訊和slot 資訊儲存了signal 和slot 函式名字的起始位置,結合上面的stringdata ,我們可以獲得函式名,同時從儲存資訊的位置,確定了signal 和slot 的索引值

我們來看以下的乙個例子,

class qtesta : public qobject ;

這是乙個繼承qobject 的類,它有兩個singal 和兩個slot 。

以下是它的qmetaobject 內容,取自由qt 工程自動生成的moc 打頭的cpp 檔案。

static

const

uint

qt_meta_data_qtesta  = ;

它的data 成員變數內容,索引號0 到11 是 「qmetaobjectprivate 「結構的資訊。

「qmetaobjectprivate 「結構如下:

struct

qmetaobjectprivate ;

我們可以看到 qt_meta_data_qtesta [4] 也就是qmetaobjectprivate 

結構中的methodcount 變數 的值為4 ,說明有四個方法(本例中2 個signal 和,2 個slot 加起來正好是4 )。又可以看到qt_meta_data_qtesta [5] 也就是qmetaobjectprivate 

結構中的methoddata 變數 的值為12 ,說明method 的資訊從qt_meta_data_qtesta

的第12 個陣列元素開始(即qt_meta_data_qtesta[12]),正好是 「 // signals: signature, parameters, type, tag, flags 」

它下面的兩行就是我們所設定的兩個signal 函式的資訊。

而在「 // slots: signature, parameters, type, tag, flags 」的下面是兩個slot 函式的資訊。

他們的資訊都是5 個一組

static

const

char

qt_meta_stringdata_qtesta  = ;

這是他的stringdata

變數的內容,裡面包含了類名(

qtesta

),第乙個signal 函式名( signala1()),

,第二個singal 函式引數名(i ),第二個signal 函式名( signala2(int) ), 第乙個slot 函式名( slota1() )

,第二個slot 函式引數名( buf,nsize ),第二個slot 函式名( slota2(char*,int) )。

每一部分都用/0 結束,這樣便於字串操作,只要加上 偏移,就能得到該字串,而不用管有多長。因為有關字串的操作,都會碰到/0 後自動終止。

結合 data 成員變數內容,來自於data 成員變數內容第一條signal 函式資訊」 8,    7,    7,    7, 0x05」

其中8 ,表示第乙個signal 函式的名字的在「 qt_meta_stringdata_qtesta 」字串的偏移位置是8 (注意/0 算乙個字元,別數錯了:p ),所以,指向它的名字的指標位置就是 qt_meta_stringdata_qtesta+8

。如果我們要拷貝它的名字,就非常簡單。

出來的值就是

」signala1()」

比如以下**,

char szsignal[256] = ;

strcpy(szsignal, qt_meta_stringdata_qtesta+8);

看這時候,用/0 的分割的好處就出來了,我們只需要知道它從什麼位置開始,不需要知道在什麼位置結束。因為strrcpy 碰到/0 就不會再拷貝了。

第二條signal 函式的資訊是「 21,   19,    7,    7, 0x05」 21

表示,第二個signal 函式名字的偏移位置是21 ,所以他的值是 signala2(int)

同理,第一條slot 函式的資訊是」 35,    7,    7,    7, 0x0a 」

所以第乙個slot 函式的偏移量是35, 得出的值是 slota1()

第二條slot 函式的資訊是「56,   44,    7,    7, 0x0a 」,得出的值是 slota2(char*,int)。

也許有看管會問,如何知道一條資訊是slot 還是signal 呢,看最後乙個引數貌似0x05 是表示的signal ,

0x0a 表示的是slot ,但我也看到過其他值。非常奇怪。

同時這幾條資訊的排列順序就是,函式的索引值

// signals: signature, parameters, type, tag, flags

8,    7,    7,    7, 0x05, // 表示signala1 函式的資訊,它的索引值0

21,   19,    7,    7, 0x05,// 表示signala2 函式的資訊,它的索引值1

// slots: signature, parameters, type, tag, flags

35,    7,    7,    7, 0x0a,// 表示slota1 函式的資訊,它的索引值2

56,   44,    7,    7, 0x0a,// 表示slota2 函式的資訊,它的索引值3

索引值將會在這個函式使用

intqtesta ::qt_metacall (qmetaobject ::call

_c , int

_id , void **_a )

_id -= 4;

}return

_id ;

}

Qt執行緒之間通過signal和slot傳遞資料

這種方法主要是為了設定自己定義的資料型別,在不同的執行緒之間進行通訊。如果自己定義的資料型別未經處理之間傳遞會報如下錯誤 qobject connect cannot queue arguments of type textandnumber make sure textandnumber is r...

深入了解Qt(三)之元signal和slot

深入了解qt主要內容 於inside qt系列,本文做了部分刪改,以便於理解。在此向原作者表示感謝!在qt訊號和槽函式這篇文章中已經詳細地介紹了訊號和槽的使用及注意事項。在這裡對其使用方面的知識就不再做介紹,只做一些相應補充。我們知道訊號和槽是用來在物件間通訊的一種機制,當乙個特定的事件發生時,si...

Pyqt 訊號(signal)和槽函式(slot)

訊號 signal 就是在特定情況下被發射 emit 的一種通告 槽函式 slot 對訊號 signal 相應的函式,接收某個物件傳送的訊號,執行某種操作。槽函式和普通函式的區別就是可與 訊號 關聯。在qt中,每乙個qobject物件和pyqt中所有繼承自qwidget的控制項 這些都是qobjec...