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

寫在前面

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

為什么要使用信號槽機制

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

Qt信號槽機制的構成

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

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

信號(Signal)

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

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

槽(Slot)

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

Qt信號槽機制的使用

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

#include <QObject>

class Counter : public QObject
{
    Q_OBJECT

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

private:
    int m_value;
};

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

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

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

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

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

最后

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

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容