Qt信號槽(signal and slot)機(jī)制初識

寫在前面

本文主要介紹Qt信號槽(signal and slot)機(jī)制,介紹Qt信號槽機(jī)制的含義,用途以及如何簡單的使用。本文基于Qt5,大部分內(nèi)容來源于其文檔,文檔鏈接在此

為什么要使用信號槽機(jī)制

Qt是一種基于C++的GUI(graphic user inferface)工具庫,而在GUI應(yīng)用中,涉及到人機(jī)交互,也就是程序需要對用戶的各種操作進(jìn)行響應(yīng),這個需求本質(zhì)上就是GUI編程中的控件之間的通信問題。基于Qt的GUI程序存在著大量的控件,如按鈕,標(biāo)簽,候選框等,這些控件在編程層面也就是以對象形式存在,因此這樣控件間的通信問題實(shí)際上就是對象間的通信問題。好了,在Qt中使用的是信號槽機(jī)制實(shí)現(xiàn)對象間的通信問題,而在其他的GUI工具庫使用稱為回調(diào)(callback)的機(jī)制。

Qt信號槽機(jī)制的構(gòu)成

在Qt中,一個對象可以向另一個對象發(fā)送信號, 一個對象可以使用槽接收其他對象發(fā)送的信號,示意圖如下:
signal_slot.png

通過使用connect操作,將一個對象的信號與另一個對象的槽構(gòu)建聯(lián)系,即對象的信號發(fā)出將會被另一個對象的槽接收,并且進(jìn)行設(shè)定的操作。

信號(Signal)

信號定義在Qt對象中,可以使用關(guān)鍵詞emit發(fā)射信號,一旦信號發(fā)出,與之相連接的槽會立即執(zhí)行對應(yīng)操作。信號在對象中通常是公開可訪問的,因此可以在任何地方發(fā)射。需注意的是使用emit發(fā)射信號時(shí),一般會立即觸發(fā)連接槽對應(yīng)的操作,因此只有當(dāng)所有與該信號相關(guān)的槽都產(chǎn)生了返回才會進(jìn)行執(zhí)行emit后面的語句,不過這個行為與信號與槽的連接方式有關(guān),可參考如下鏈接

在Qt中,默認(rèn)定義了很多信號,而不需要我們考慮。MOC(meta-object compiler)會對用戶編寫的.cpp文件進(jìn)行掃描處理,生成包含Qt內(nèi)容的.cpp文件。

槽(Slot)

槽在Qt對象中定義為函數(shù),當(dāng)所連接的信號發(fā)出時(shí),槽函數(shù)會立即被調(diào)用,由于槽函數(shù)也是定義為C++函數(shù),因此可以也直接調(diào)用。在C++定義中,一般使用關(guān)鍵詞slots聲明Qt對象包含的槽函數(shù)。

Qt信號槽機(jī)制的使用

在實(shí)踐中,我們?nèi)绻胍褂肣t的信號槽機(jī)制就需要按照Qt的語法規(guī)范進(jìn)行編程。在自定義的對象中,我們除了需要繼承QObject之外,還需要在對象定義中使用關(guān)鍵詞Q_OBJECT。因?yàn)镼t會使用MOC對所有編寫的源文件進(jìn)行掃描,只有包含Q_OBJECT的自定義對象才會有Qt提供的各種功能。一個類似的對象定義如下:

#include <QObject>

class Counter : public QObject
{
    Q_OBJECT

public:
    Counter() { m_value = 0; }
    // 以下成員函數(shù)是const的特殊用法,表示該成員函數(shù)不能對類的數(shù)據(jù)成員進(jìn)行修改。
    int value() const { return m_value; }
// 使用關(guān)鍵詞slots表示該對象存在的槽函數(shù),槽函數(shù)可以直接調(diào)用也可以通過信號觸發(fā)
public slots:
    void setValue(int value);
// 使用關(guān)鍵詞signals表示該對象可發(fā)射的信號,類似于一個函數(shù)聲明,參數(shù)表示信號發(fā)射時(shí)將給槽提供的參數(shù)。
signals:
    void valueChanged(int newValue);

private:
    int m_value;
};

在類對象的定義中,槽函數(shù)是需要我們自己編程實(shí)現(xiàn)的,而信號那塊不需要我們考慮。

void Counter::setValue(int value)
{
    if (value != m_value) {
        m_value = value;
        // 使用關(guān)鍵詞emit發(fā)射信號
        emit valueChanged(value);
    }
}

在完成對象的定義后,槽函數(shù)及信號都已經(jīng)存在,接下來就是需要根據(jù)我們的需要將信號和槽進(jìn)行連接,使用connect進(jìn)行連接,一個示例如下:

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

將信號與槽進(jìn)行連接后,如果信號發(fā)出,則對應(yīng)的槽函數(shù)將被調(diào)用。在上述示例中,對象a設(shè)置值后會發(fā)出valueChanged的信號,這會導(dǎo)致對象b中的槽函數(shù)觸發(fā),而對象b的信號雖然發(fā)出,但是并沒有與對象b中的槽函數(shù)進(jìn)行連接,因此對象a中槽函數(shù)不會被觸發(fā)。

最后

我們知道在Qt中使用的是信號槽機(jī)制進(jìn)行對象間的通信,因此如果有對象間通信的需求,可以依據(jù)Qt約定的規(guī)范進(jìn)行編程。信號與槽的連接是基本的一步,但是在實(shí)際運(yùn)用中我們可能會遇到信號槽連接的高級運(yùn)用或者不同類型的連接,這些高級用法仍然是在基本的概念上進(jìn)行的,在構(gòu)建基本的認(rèn)識后,可以慢慢分析一些高級用法的原理。

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