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

2021-09-07 06:32:40 字數 3188 閱讀 8397

深入了解qt主要內容**於inside qt系列,本文做了部分刪改,以便於理解。在此向原作者表示感謝!

qt訊號和槽函式這篇文章中已經詳細地介紹了訊號和槽的使用及注意事項。在這裡對其使用方面的知識就不再做介紹,只做一些相應補充。

我們知道訊號和槽是用來在物件間通訊的一種機制,當乙個特定的事件發生時,signal會被emit,slot呼叫時用來響應響應的signal。signal和slot機制是型別安全的,signal和slot必須互相匹配(實際上乙個slot引數可以比對應的signal的引數少,因為它可忽略多餘的引數)。signal和slot是鬆散的配對關係,發出signal的物件不關係是哪個物件執行slot函式,也不關心有多少個slot鏈結了當前的signal。signal不需要我們實現,它會有moc自動生成,並且它永遠不能有返回值。

訊號和槽的關係如下圖所示:

例如:connect(ui->pushbtn,signal(clicked()),ui->lineedit,slot(clear()));

clicked()是qpushbutton的訊號,clear()是qlineedit的方法。

我們都知道,把乙個signal和slot連線起來,需要使用qobject類的connect方法,它的作用就是把乙個object的signal和另外乙個object的slot連線起來,以達到物件間通訊的目的。

connect 在幕後到底都做了些什麼事情?為什麼emit乙個signal後,相應的slot都會被呼叫?

signal和slot巨集定義

在這裡signal和slot的名字都被包含在了兩個大寫的signal和slot中,這兩個是什麼呢?原來signal 和 slot 是qt定義的兩個巨集。

# define slot(a)      」1

″#a

# define signal(a) 」

2″#a

然後,會去檢查傳送signal的物件是否有這個signal,方法就是查詢這個物件的class所對應的staticmetaobject物件中所包含的d.stringdata所指向的字串中是否包含這個signal的名字,在這個檢查過程中,就會用到d.data所指向的那一串整數,通過這些整數值來計算每乙個具體字串的起始位址。同理,還會使用同樣的方法去檢查slot,看響應這個signal的物件是否包含有相應的slot。這兩個檢查的任何乙個如果失敗的話,connect函式就失敗了,返回false。

前面的步驟都是在做一些必要的檢查工作,下一步,就是要把傳送signal的物件和響應signal的物件關聯起來。在qobject的私有資料類qobjectprivate中,有下面這些資料結構來儲存這些資訊:

class qobjectprivate : public

qobjectdata

;

typedef qlist

; connectionlist;

qobjectconnectionlistvector *connectionlists;

struct

sender

; qlist

senders;

};

在傳送signal的物件中,每乙個signal和slot的connection,都會建立乙個qobjectprivate::connection物件,並且把這個物件儲存到connectionlist這個vector裡面去。

在響應signal的物件中,同樣,也是每乙個signal和slot的connection,都會乙個建立乙個sender物件,並且把這個物件附加在senders這個列表中。

以上就是connect的過程,其中,建立qobjectprivate::connection物件和sender物件的過程有一點點複雜,需要仔細思考才可以,有興趣的朋友可以去讀一下源**。

emit幕後的故事

當emit signal的時候,與這個signal相連的slot函式就會被呼叫,那麼這個呼叫時如何發生的呢?

看段**:

class zmytestobj : public

qobject

;

moc編譯器在做完預處理之後的**如下:

void

zmytestobj::sigmenuclicked()

void

zmytestobj::sigbtnclicked()

每乙個signal都會被轉換為乙個與之相對應的成員函式。也就是說,當我們寫下這樣一行**:emit sigbtnclicked();當程式執行到這裡的時候,實際上就是呼叫了void zmytestobj::sigbtnclicked() 這個函式。

void zmytestobj::sigmenuclicked()  void zmytestobj::sigbtnclicked(),它們唯一的區別就是呼叫 qmetaobject::activate 函式時給出的引數不同,乙個是0,乙個是1,它們的含義是什麼呢?它們表示是這個類中的第幾個signal被傳送出來了,回頭再去看標頭檔案就會發現它們就 是在這個類定義中,signal定義出現的順序,這個引數可是非常重要的,它直接決定了進入這個函式體之後所發生的事情。

當執行流程進入到qmetaobject::activate函式中後,會先從connectionlists這個變數中取出與這個signal相對應的connection list,它根據的就是剛才所傳入進來的signal index。這個connection list中儲存了所有和這個signal相鏈結的slot的資訊,每一對connection(即:signal和slot的連線)是這個list中的一項。

在每個一具體的鏈結記錄中,還儲存了這個鏈結的型別,是自動鏈結型別,還是佇列鏈結型別,或者是阻塞鏈結型別,不同的型別處理方法還不一樣的。

對於直接鏈結的型別,先找到接收這個signal的物件的指標,然後是處理這個signal的slot的index,已經是否有需要處理的引數,然後就使用這些資訊去呼叫receiver的qt_metcall 方法。在qt_metcall方法中就簡單了,根據slot的index,乙個大switch語句,呼叫相應的slot函式就ok了。

Ajax之深入了解

上一節,我們說了一些ajax的基礎知識,包括常用的get方法,現在,我們接著來講講post方法,以及利用get方法或post方法實現分頁顯示的功能。以下我們來說說get和post兩種方法的區別。詳見 get方法 建立ajax物件 建立鏈結 xhr.open get getcity?city city...

Nginx深入了解 高階 三

nginx負載均衡 load balance,簡稱lb 是一種伺服器或網路裝置的集群技術。負載均衡將特定的業務 網路服務 網路流量等 分擔給多個伺服器或網路裝置,從而提高了業務處理能力,保證了業務的高可用性。nginx負載均衡示意圖 nginx負載均衡原理就是將所有客戶端的請求通過proxy pas...

Nginx深入了解 基礎 三

nginx有很多模組配置,包括官方模組和第三方模組。syntax stub status default context server,location例如 syntax sub filter last modified on off 主要用於快取 default sub filter last m...