鍍金池/ 教程/ C/ 深入了解信號(hào)槽
Qt 容器和算法拾遺
自定義 model 之一
反走樣
Hello, world!
Qt 容器類(lèi)之關(guān)聯(lián)存儲(chǔ)容器
QStringListModel
拖放技術(shù)之一
狀態(tài)欄
QTreeWidget
拖放技術(shù)之二
通用算法
event()
Qt 學(xué)習(xí)之路(18): Qt 標(biāo)準(zhǔn)對(duì)話(huà)框之 QInputDialog
Qt 容器類(lèi)之遍歷器和隱式數(shù)據(jù)共享
QListWidget
Meta-Object 系統(tǒng)
事件接收與忽略
Qt 學(xué)習(xí)之路(tip): parent 參數(shù)
Qt 標(biāo)準(zhǔn)對(duì)話(huà)框之 QColorDialog
QPainter(續(xù))
國(guó)際化(下)
漸變填充
自定義委托
創(chuàng)建 shared library
model-view 架構(gòu)
Graphics View Framework
自定義拖放數(shù)據(jù)對(duì)象
QSortFilterProxyModel
國(guó)際化(上)
組件布局
自定義 Model 之三
事件過(guò)濾器
QDirModel
Hello, world!(續(xù))
Qt 標(biāo)準(zhǔn)對(duì)話(huà)框之 QFileDialog
自定義 model 之二
深入了解信號(hào)槽
坐標(biāo)變換
剪貼板操作
QTableWidget
QByteArray 和 QVariant
創(chuàng)建一個(gè)對(duì)話(huà)框(下)
Qt 學(xué)習(xí)之路(32): 一個(gè)簡(jiǎn)易畫(huà)板的實(shí)現(xiàn)(Graphics View)
文本文件讀寫(xiě)
自定義事件
編寫(xiě)跨平臺(tái)的程序
MainWindow
初探信號(hào)槽
Qt 學(xué)習(xí)之路(17): Qt 標(biāo)準(zhǔn)對(duì)話(huà)框之 QMessageBox
繪圖設(shè)備
菜單和工具條(續(xù))
二進(jìn)制文件讀寫(xiě)
QString
事件(event)
菜單和工具條
QPainter
Qt 容器類(lèi)之順序存儲(chǔ)容器
進(jìn)程間交互
API 文檔的使用
創(chuàng)建一個(gè)對(duì)話(huà)框(上)
一個(gè)簡(jiǎn)易畫(huà)板的實(shí)現(xiàn)(QWidget)

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

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

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

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

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

這里,sender 和 receiver 都是 QObject 類(lèi)型的,singal 和 slot 都是沒(méi)有參數(shù)名稱(chēng)的函數(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ù)、類(lèi)型以及出現(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 類(lèi),就可以使用信號(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)連接嗎?如果沒(méi)有 if,當(dāng)出現(xiàn)了循環(huán)連接的時(shí)候就會(huì)產(chǎn)生無(wú)限遞歸。

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

上一篇:反走樣下一篇:坐標(biāo)變換