Qt的信號和槽機制(Signals & Slots)


原文:官方幫助文檔:https://doc.qt.io/qt-5/signalsandslots.html

信號和槽(Signals & Slots)用於對象之間的通信。信號和槽機制是Qt的核心特性,可能也是與其他框架所提供的特性最不同的部分。信號和槽是由Qt的元對象系統(The Meta-Object System)實現的。

產生背景

在GUI編程中,當我們更改一個小部件時,我們通常希望通知另一個小部件。更一般地說,我們希望任何類型的對象都能夠彼此通信。

例如,如果用戶單擊關閉按鈕,我們可能希望調用窗口的Close()函數。

其他工具包使用回調實現這種通信。回調是指向函數的指針,因此,如果希望某個處理函數通知你某個事件,則需要將一個指向另一個函數(回調)的指針傳遞給處理函數。然後處理函數在適當的時候調用回調。雖然使用這種方法的成功框架確實存在,但是回調可能不夠直觀,而且在確保回調參數的類型正確性方面可能會遇到問題。

信號與槽

在Qt中,我們有一種替代回調技術的方法:使用信號和槽。當特定事件發生時發出信號。Qt的widgets有許多預定義的信號,但是我們總是可以子類化widgets來添加我們自己的信號。槽是響應特定信號而被調用的函數。Qt的窗口小部件有許多預定義的槽,但通常的做法是子類化窗口小部件並添加自己的槽,以便處理需要的信號。

信號和槽機制是類型安全的:信號的簽名必須與接收槽的簽名匹配。(事實上,槽的簽名可能比它接收到的信號短,因爲它可以忽略額外的參數。)由於簽名是兼容的,編譯器可以幫助我們在使用基於函數指針的語法時檢測類型不匹配。基於字符串的信號和槽語法將在運行時檢測類型不匹配。信號和槽是鬆散耦合的:發出信號的類既不知道也不關心哪個槽接收信號。Qt的信號和槽機制確保,如果你將信號連接到槽,該槽將在正確的時間與信號的參數一起被調用。信號和槽可以接受任意數量的任意類型的參數。它們是完全類型安全的。

繼承自QObject的所有類都可以包含信號和槽。當對象改變它的一些狀態時,就會發出信號。它不知道也不關心是否有誰正在接收它發出的信號。這是真正的信息封裝,並確保對象可以作爲軟件組件使用。

槽可以用來接收信號,但它們也是普通的成員函數。就像一個對象不知道是否有任何東西接收到它的信號一樣,一個槽也不知道是否有任何信號連接到它。這確保了可以用Qt創建真正獨立的組件
對象的connect
你可以將任意多的信號連接到一個槽,一個信號可以連接到任意多的槽。甚至可以將一個信號直接連接到另一個信號。(這將在第一個信號發出時立即發出第二個信號。)

信號和槽一起構成了一個強大的組件編程機制。

信號

當對象的內部狀態以某種方式發生變化時,對象的客戶端或所有者可能會對此感興趣,就會發出信號。信號是公共訪問函數,可以從任何地方發出,但是我們建議只從定義信號及其子類的類發出信號。

當一個信號被髮出時,連接到它的槽通常會立即執行,就像一個普通的函數調用一樣。當發生這種情況時,信號和槽機制完全獨立於任何GUI事件循環。當所有槽返回後,emit語句後面的代碼就會執行。在使用排隊連接時,情況略有不同;在這種情況下,emit關鍵字後面的代碼將立即繼續執行,槽將在稍後執行。

如果幾個槽連接到一個信號,當信號發出時,槽將依次執行。(這個順序無法保證。)

信號是由moc(元對象編譯器)自動生成的,不能在.cpp文件中實現。它們永遠不能有返回類型(即使用void)。

關於參數的注意事項:我們的經驗表明,如果信號和槽不使用特殊類型,那麼它們的可重用性更好。如果QScrollBar::valueChanged()使用一種特殊類型,例如假想的QScrollBar::Range,那麼它只能連接到專爲QScrollBar設計的槽。將不同的輸入小部件連接在一起是不可能的。

當連接到槽的信號發出時,就會調用槽。槽是普通的c++函數,可以正常調用。它們唯一的特點是可以將信號連接到它們身上。

因爲槽是普通的成員函數,所以它們在直接調用時遵循普通的c++規則。但是,作爲槽,任何組件都可以通過信號槽連接調用它們無論其訪問級別如何。這意味着從任意類的實例發出的信號可以導致在不相關類的實例中調用私有槽。

你還可以將槽定義爲虛擬的,這在實踐中非常有用。

與回調相比,信號和槽的速度稍微慢一些,因爲它們提供了更大的靈活性,儘管實際應用的差異並不大。一般來說,通過發出信號來調用槽的速度比使用非虛擬函數直接調用的速度大約慢十倍。這是定位連接對象、安全遍歷所有連接(即檢查後續接收器在發射過程中沒有被銷燬)和並以通用方式編組任何參數所需的開銷。雖然10倍差距聽起來可能很多,但是它比任何新建操作或刪除操作的開銷要小得多。只要執行後臺需要新建或刪除字符串、向量或列表操作,信號和槽開銷就只佔整個函數調用開銷的很小一部分。 信號和槽機制的簡單性和靈活性非常值得這些開銷,用戶甚至不會注意到這些開銷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章