Qt 深入了解信號(hào)槽

2018-10-04 10:06 更新

深入了解信號(hào)槽

信號(hào)槽機(jī)制是 Qt 編程的基礎(chǔ)。通過信號(hào)槽,能夠使 Qt 各組件在不知道對(duì)方的情形下能夠相互通訊。這就將類之間的關(guān)系做了最大程度的解耦。

槽函數(shù)和普通的 C++ 成員函數(shù)沒有很大的區(qū)別。它們也可以使 virtual 的;可以被重寫;可以使public、protected 或者 private 的;可以由其它的 C++ 函數(shù)調(diào)用;參數(shù)可以是任何類型的。如果要說(shuō)區(qū)別,那就是,槽函數(shù)可以和一個(gè)信號(hào)相連接,當(dāng)這個(gè)信號(hào)發(fā)生時(shí),它可以被自動(dòng)調(diào)用。

connect()語(yǔ)句的原型類似于:

connect(sender, SIGNAL(signal), receiver, SLOT(slot));

這里,sender 和 receiver 都是 QObject 類型的,singal 和 slot 都是沒有參數(shù)名稱的函數(shù)簽名。SINGAL()和SLOT()宏用于把參數(shù)轉(zhuǎn)換成字符串。

深入的說(shuō),信號(hào)槽還有更多可能的用法,如下所示。

一個(gè)信號(hào)可以和多個(gè)槽相連:

connect(slider, SIGNAL(valueChanged(int)),
              spinBox, SLOT(setValue(int))); 
connect(slider, SIGNAL(valueChanged(int)),
              this, SLOT(updateStatusBarIndicator(int)));

注意,如果是這種情況,這些槽會(huì)一個(gè)接一個(gè)的被調(diào)用,但是它們的調(diào)用順序是不確定的。

多個(gè)信號(hào)可以連接到一個(gè)槽:

connect(lcd, SIGNAL(overflow()),
              this, SLOT(handleMathError())); 
connect(calculator, SIGNAL(divisionByZero()),
              this, SLOT(handleMathError()));

這是說(shuō),只要任意一個(gè)信號(hào)發(fā)出,這個(gè)槽就會(huì)被調(diào)用。

一個(gè)信號(hào)可以連接到另外的一個(gè)信號(hào):

connect(lineEdit, SIGNAL(textChanged(const QString &)),
              this, SIGNAL(updateRecord(const QString &)));

這是說(shuō),當(dāng)?shù)谝粋€(gè)信號(hào)發(fā)出時(shí),第二個(gè)信號(hào)被發(fā)出。除此之外,這種信號(hào)-信號(hào)的形式和信號(hào)-槽的形式?jīng)]有什么區(qū)別。

槽可以被取消鏈接:

disconnect(lcd, SIGNAL(overflow()),
                 this, SLOT(handleMathError()));

這種情況并不經(jīng)常出現(xiàn),因?yàn)楫?dāng)一個(gè)對(duì)象 delete 之后,Qt 自動(dòng)取消所有連接到這個(gè)對(duì)象上面的槽。

為了正確的連接信號(hào)槽,信號(hào)和槽的參數(shù)個(gè)數(shù)、類型以及出現(xiàn)的順序都必須相同,例如:

connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
              this, SLOT(processReply(int, const QString &)));

這里有一種例外情況,如果信號(hào)的參數(shù)多于槽的參數(shù),那么這個(gè)參數(shù)之后的那些參數(shù)都會(huì)被忽略掉,例如:

connect(ftp, SIGNAL(rawCommandReply(int, const QString &)), 
            this, SLOT(checkErrorCode(int)));

這里,const QString &這個(gè)參數(shù)就會(huì)被槽忽略掉。

如果信號(hào)槽的參數(shù)不相容,或者是信號(hào)或槽有一個(gè)不存在,或者在信號(hào)槽的連接中出現(xiàn)了參數(shù)名字,在Debug 模式下編譯的時(shí)候,Qt 都會(huì)很智能的給出警告。

在這之前,我們僅僅在 widgets 中使用到了信號(hào)槽,但是,注意到 connect()函數(shù)其實(shí)是在 QObject 中實(shí)現(xiàn)的,并不局限于 GUI,因此,只要我們繼承 QObject 類,就可以使用信號(hào)槽機(jī)制了:

class Employee : public QObject 
{ 
        Q_OBJECT 
public: 
        Employee() { mySalary = 0; }  
        int salary() const { return mySalary; } 

public slots: 
        void setSalary(int newSalary); 

signals: 
        void salaryChanged(int newSalary); 

private: 
        int mySalary; 
};

在使用時(shí),我們給出下面的代碼:

void Employee::setSalary(int newSalary) 
{ 
        if (newSalary != mySalary) { 
                mySalary = newSalary; 
                emit salaryChanged(mySalary); 
        } 
}

這樣,當(dāng) setSalary()調(diào)用的時(shí)候,就會(huì)發(fā)出 salaryChanged()信號(hào)。注意這里的 if 判斷,這是避免遞歸的方式!還記得前面提到的循環(huán)連接嗎?如果沒有 if,當(dāng)出現(xiàn)了循環(huán)連接的時(shí)候就會(huì)產(chǎn)生無(wú)限遞歸。

本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/194031

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)