Qt的Signals 和 Slots詳解

Qt::AutoConnection的signal-slot連接是在運(yùn)行時(shí)確定連接類型,多線程安全的。

Qt中的關(guān)鍵字:signals 其實(shí)就是public;而slots則什么都沒有。

Signals 和 Slots 用于對象間的通信(communication between objects)。這種機(jī)制是Qt區(qū)別于其他框架的主要特點(diǎn)。這種機(jī)制是靠Qt的meta-object system實(shí)現(xiàn)的。

介紹

很多框架使用callback技術(shù)(MFC,CVI等)。一個(gè) callback 其實(shí)就是一個(gè)函數(shù)指針,但是Qt認(rèn)為callback并不直觀,而且在callback參數(shù)上容易出問題。

信號與槽

在Qt中使用另一種方案:信號與槽。信號在特定事件發(fā)生時(shí)被發(fā)射。Qt widgets有很多預(yù)定義的信號。我們可以子類化widgets來添加自己的信號。槽函數(shù)在所連接信號發(fā)射后被調(diào)用,作為事件的響應(yīng)。? ? Qt widgets有很多預(yù)定義的槽。實(shí)際中我們經(jīng)常子類化widget來添加自己的槽函數(shù),來響應(yīng)感興趣的信號。


信號與槽:對象間通信

信號與槽機(jī)制是類型安全的:信號的簽名必須和槽一致(實(shí)際槽的簽名可以比信號更短,忽略部分參數(shù))。由于簽名兼容,編譯器可以幫助我們檢查類型是否匹配。基于字符串的 SIGNAL 和 SLOT 語法可以在運(yùn)行階段檢查類型匹配。

所有繼承自QObject的類都可以包含信號和槽。槽函數(shù)既可以用來接收信號,也可以當(dāng)做普通函數(shù)使用。

信號和槽可以是一對多、多對一。也可以把一個(gè)信號連接到另一個(gè)信號(這樣第一個(gè)信號發(fā)射后會接著發(fā)射第二個(gè)信號)。callback技術(shù)(即函數(shù)指針)只能是一對一。

信號/槽非常類似于C#中事件(event)的發(fā)布和訂閱。

信號

信號是 public 類型的,可以從任何地方發(fā)射。但是推薦在定義信號的類內(nèi)部發(fā)射(signals are public access functions and can be emitted from any where, but we recommend to only emit them from the class that defines the signals and its subclasses)。

Qt中的關(guān)鍵字:signals 其實(shí)就是public;而slots則什么都沒有。

(信號非常類似C#中的事件event,可以被訂閱)

當(dāng)信號發(fā)射時(shí),連接的槽函數(shù)通常立即執(zhí)行(direct connection),就像普通的函數(shù)調(diào)用。此時(shí)信號和槽機(jī)制與GUI的事件循環(huán)是獨(dú)立的。emit 之后的代碼在所有槽函數(shù)返回后才會被執(zhí)行(正常,此時(shí)的信號-槽,就是函數(shù)指針-函數(shù))。這和 queued connections 不同,后者是立即執(zhí)行 emit 之后的代碼,而槽函數(shù)在晚些時(shí)候執(zhí)行。

如果多個(gè)槽連接到一個(gè)信號,當(dāng)信號發(fā)射時(shí),槽函數(shù)的執(zhí)行順序就是連接的順序。

信號由moc自動生成,不可以在.cpp文件中實(shí)現(xiàn),而且也不能有返回類型(即只能使用void)。

槽函數(shù)就是普通的C++函數(shù)。唯一特別的地方是:可以連接到信號。

槽函數(shù)可以通過 信號-槽 的連接而被任何組件調(diào)用,這與槽的訪問權(quán)限無關(guān)。這意味著private 的槽也可以被信號調(diào)用。(However, as slots, they can be invoked by any component, regardless of its access level, via a signal-slot connection.This means that a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class)

槽函數(shù)是普通的成員函數(shù)。也可以定義成virtual類型,非常有用。

信號-槽機(jī)制比callback機(jī)制的速度略慢,這是增加了靈活性的代價(jià),但是差異并不大。通常,發(fā)射一個(gè)信號來調(diào)用槽函數(shù),通常比直接調(diào)用函數(shù)慢10倍(10 times slower tha calling the receivers directly),時(shí)間主要用來確定接收對象,來安全的遍歷連接(例如檢查后續(xù)的信號接收者沒有被銷毀),來封送參數(shù)。

信號-槽機(jī)制消耗的時(shí)間比 new 和delete所消耗的時(shí)間更短。考慮到它的靈活性,這些實(shí)現(xiàn)消耗是值得的。

例子

#include <QObject>

? class Counter : public QObject

? {

? ? ? Q_OBJECT

? public:

? ? ? Counter() { m_value = 0; }

? ? ? int value() const { return m_value; }

? public slots:

? ? ? void setValue(int value);

? signals:

? ? ? void valueChanged(int newValue);

? private:

? ? ? int m_value;

? };

包含信號和槽的類必須滿足兩個(gè)條件:

1. 在聲明的最頂部使用 Q_OBJECT;

2.直接或間接繼承自QObject。

void Counter::setValue(int value)

? {

? ? ? if (value != m_value) {

? ? ? ? ? m_value = value;

? ? ? ? ? emit valueChanged(value);

? ? ? }

? }

Counter a, b;? ? ? QObject::connect(&a, &Counter::valueChanged,? ? ? ? ? ? ? ? ? ? ? &b, &Counter::setValue);?

a.setValue(12);? ? // a.value() == 12, b.value() == 12

? ? b.setValue(48);? ? // a.value() == 12, b.value() == 48

信號和槽的連接類型

Qt::AutoConnection

默認(rèn)連接方式。當(dāng)receiver在于發(fā)射信號的線程里時(shí)(線程親和性),使用的是Qt::DirectConnection. 多線程時(shí)則使用Qt::QueuedConnnection。連接類型在信號發(fā)射時(shí)確定(運(yùn)行時(shí),而非編譯時(shí))。

Qt::DirectConnection

信號發(fā)射時(shí)立即調(diào)用槽函數(shù)。槽在信號發(fā)射的線程里執(zhí)行。

Qt::QueuedConnnection

當(dāng)控制權(quán)回到receiver所在線程時(shí)才執(zhí)行槽函數(shù)。槽函數(shù)在receiver的線程里執(zhí)行。

Qt::BlockingQueuedConnection

和QueuedConnection類似。但是發(fā)射信號的線程會阻塞,直到槽函數(shù)返回。當(dāng)receiver和sender在同一個(gè)線程里時(shí),不可以使用該方式,否則會發(fā)生死鎖。

Qt::UniqueConnection

該類型可以和上面的類型配合,用或“|”處理即可。當(dāng)連接已經(jīng)存在時(shí),再次連接會失敗。其實(shí)就是為了保證連接的唯一性。

注意:當(dāng)使用QueuedConnection時(shí),參數(shù)類型必須是 Qt 的 meta-object system 知道的類型,因?yàn)镼t要拷貝參數(shù)。可以connect()前調(diào)用qRegisterMetaType()來注冊數(shù)據(jù)類型。

關(guān)于信號和槽在多線程中的使用,參考“QObjects和多線程”。



參考Qt官方文檔:"Signals & Slots".

QT多線程深入分析






最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,004評論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 為什么在頭文件中有的是使用前置聲明,而有的是包含頭文件? 如下代碼: 前置聲明(forward declarati...
    Joe_HUST閱讀 1,310評論 0 6
  • 信號和槽(Signals and Slots) Qt庫第一個(gè)認(rèn)識到在幾乎所有情況下,程序員不需要或甚至不想知道所有...
    珞珈村下山閱讀 9,856評論 0 23
  • 1、概述 信號槽是 Qt 框架引以為豪的機(jī)制之一。所謂信號槽,實(shí)際就是觀察者模式。當(dāng)某個(gè)事件發(fā)生之后,比如,按鈕檢...
    你的社交帳號昵閱讀 45,349評論 0 9
  • 韓元旭、余橙、沈開洋 Qt介紹 Qt是一個(gè)跨平臺的C++圖形用戶界面應(yīng)用程序框架。它早在1991年奇趣科技公司兩位...
    開洋_shen閱讀 16,206評論 4 24
  • 轉(zhuǎn)自:作者簡介作者:唐新華 (xhsmart@263.net)軟件工程師 ?? 信號和槽作為QT的核心機(jī)制在QT編...
    njukay閱讀 1,352評論 0 49