QT 的信號(hào)與槽機(jī)制(3)
信號(hào)和槽是一種高級(jí)接口,應(yīng)用于對(duì)象之間的通信,它是 QT 的核心特性。要正確的處理信號(hào)和槽,必須借助一個(gè)稱(chēng)為 moc(Meta Object Compiler)的 QT 工具,該工具是一個(gè) C++ 預(yù)處理程序,它為高層次的事件處理自動(dòng)生成所需要的附加代碼。 信號(hào)和槽能攜帶任意數(shù)量和任意類(lèi)型的參數(shù)。我們可以將很多信號(hào)與單個(gè)的槽進(jìn)行連接,也可以將單個(gè)的信號(hào)與很多的槽進(jìn)行連接,(當(dāng)這個(gè)信號(hào)被發(fā)射時(shí),這些槽將會(huì)一個(gè)接一個(gè)地 執(zhí)行,但是它們執(zhí)行的順序?qū)?huì)是隨機(jī)的、不確定的,我們不能人為地指定哪個(gè)先執(zhí)行、哪個(gè)后執(zhí)行。)甚至于將一個(gè)信號(hào)與另外一個(gè)信號(hào)相連接,這時(shí)無(wú)論第一個(gè)信號(hào)什么時(shí)候發(fā)射系統(tǒng)都將立刻發(fā)射第二個(gè)信號(hào)。總之,信號(hào)與槽構(gòu)造了一個(gè)強(qiáng)大的部件編程機(jī)制。
信號(hào)(signals)
信號(hào)只需要在頭文件中做聲明,不需要在cpp中實(shí)現(xiàn)。放在QT自定義關(guān)鍵字signals下,在此之前一定要加上Q_OBJECT宏!
在編程中,一般使用的是控件內(nèi)部定義好的信號(hào)。
如:QTreeWidget類(lèi)下的 signals:
void currentItemChanged ( QTreeWidgetItem * current, QTreeWidgetItem * previous )
void itemActivated ( QTreeWidgetItem * item, int column )
void itemChanged ( QTreeWidgetItem * item, int column )
void itemClicked ( QTreeWidgetItem * item, int column )
void itemCollapsed ( QTreeWidgetItem * item )
void itemDoubleClicked ( QTreeWidgetItem * item, int column )
void itemEntered ( QTreeWidgetItem * item, int column )
void itemExpanded ( QTreeWidgetItem * item )
void itemPressed ( QTreeWidgetItem * item, int column )
void itemSelectionChanged ()
也可以自定義信號(hào),并通過(guò)emit在代碼中發(fā)射信號(hào)。
// ------------ sender.h -----------
class sender : public QObject
{
Q_OBJECT
public:
void doSend();
signals:
void send(int);
};
// ------------ sender.cpp -----------
#include "sender.h"
void sender :: doSend()
{
emit send(40);
}
槽(slots)
槽和普通的C++成員函數(shù)幾乎是一樣的(可以是虛函數(shù),可以被重載,可以是public slots、protected slots、private slots,可以被其他C++成員函數(shù)直接調(diào)用;唯一不同的是:槽還可以和信號(hào)連接在一起,在這種情況下,信號(hào)被發(fā)射時(shí),會(huì)自動(dòng)調(diào)用這個(gè)槽。)槽不需要信號(hào)傳過(guò)來(lái)的參數(shù)時(shí),可以不要參數(shù);但槽一旦要參數(shù),其參數(shù)個(gè)數(shù),類(lèi)型,順序必須要和對(duì)應(yīng)的信號(hào)保持一致。另外,槽的參數(shù)不能有缺省值。
// ------------ receiver.h -----------
class receiver : public QObject
{
Q_OBJECT
public slots:
void recv(int);
};
// ------------ Receiver.cpp -----------
void receiver :: recv(int n)
{
qDebug()<<"recv number: "<<n<<endl;
}
關(guān)聯(lián)信號(hào)和槽(connect)
可以使用QObject類(lèi)的靜態(tài)成員函數(shù)connect來(lái)建立信號(hào)的槽的關(guān)聯(lián)
QObject::connect是靜態(tài)函數(shù),返回值bool類(lèi)型.
static bool QObject::connect ( const QObject * sender, const char * signal,const QObject * receiver, const char * member );
具體的調(diào)用為:connect(sender, SIGNAL(signal), receiver, SLOT(slot)); 其中sender和receiver為QObject類(lèi)對(duì)象的指針; SIGNAL宏和SLOT宏將信號(hào)的槽轉(zhuǎn)換成字符串。
sender s;
receiver r;
QObject::connect(&s, SIGNAL(send(int)), &r, SLOT(recv(int)));
注:在connect函數(shù)中信號(hào)函數(shù)和槽函數(shù)若有參數(shù),只能寫(xiě)出參數(shù)類(lèi)型,而不能也將變量名寫(xiě)出;否則,連接會(huì)失敗!
斷開(kāi)信號(hào)和槽(disconnect)
當(dāng)信號(hào)和槽沒(méi)有必要繼續(xù)保持連接時(shí),可以通過(guò)調(diào)用disconnect來(lái)斷開(kāi)它們。
static bool QObject::disconnect (const QObject * sender, const char * signal, const Object * receiver, const char * slot)
有三種情況必須使用 disconnect() 函數(shù):
(1)斷開(kāi)與某個(gè)對(duì)象相關(guān)聯(lián)的任何對(duì)象。
disconnect(sender, 0, 0, 0) ;
//或者
sender->disconnect();
(2)斷開(kāi)與某個(gè)特定信號(hào)的任何關(guān)聯(lián)。
disconnect(sender, SIGNAL(signal()), 0, 0);
//或者
sender->disconnect(SIGNAL(signal()));
(3)斷開(kāi)兩個(gè)對(duì)象之間的關(guān)聯(lián)。
disconnect(sender, 0, receiver, 0);
//或者
sender->disconnect(receiver);
轉(zhuǎn)自: