信號(hào)和槽是Qt特有的信息傳輸驅(qū)動(dòng)機(jī)制,是Qt程序設(shè)計(jì)中的重要基礎(chǔ),它可以讓程序員在互不相干的對(duì)象之間建立聯(lián)系。
槽本質(zhì)上是類的成員函數(shù),其參數(shù)可以是任意類型,它與普通的C++成員函數(shù)幾乎沒有區(qū)別,它可以是虛函數(shù);也可以被重載函數(shù);可以是公有的、保護(hù)的或私有的,也可以被其它C++成員函數(shù)調(diào)用,和普通的類成員函數(shù)唯一不同的是:槽還可以和信號(hào)連接在一起,每當(dāng)和槽連接的信號(hào)被發(fā)射時(shí),就會(huì)自動(dòng)調(diào)用這個(gè)槽。
connect()語法形式如下:
connect(sender,SIGNAL(signal),receiver,SLOT(slot));
這里的sender是發(fā)送信號(hào)的對(duì)象的指針,receiver是包含槽的對(duì)象的指針,signal是被發(fā)送的信號(hào),slot是接受信號(hào)的槽,他們都是不帶參數(shù)的函數(shù)名。SIGNAL()宏和SLOT()宏會(huì)把他們的參數(shù)轉(zhuǎn)換成相應(yīng)的字符串。對(duì)于信號(hào)和槽,還具有以下特點(diǎn)。
1.一個(gè)信號(hào)可以連接多個(gè)槽
connect(sender,SIGNAL(signal),receiver,SLOT(slotA));
connect(sender,SIGNAL(signal),receiver,SLOT(slotB));
當(dāng)這一信號(hào)發(fā)射時(shí),會(huì)以不確定的順序一個(gè)接一個(gè)的調(diào)用這個(gè)信號(hào)連接的所有槽
2.多個(gè)信號(hào)可以連接同一個(gè)槽
connect(sender,SIGNAL(signalA),receiver,SLOT(slot));
connect(sender,SIGNAL(signalB),receiver,SLOT(slot));
無論哪個(gè)信號(hào)被發(fā)射,這個(gè)槽都會(huì)被調(diào)用
3.一個(gè)信號(hào)可以連接另外一個(gè)信號(hào)
connect(sender,SIGNAL(signalA),receiver,SIGNAL(signalB));
當(dāng)信號(hào)A發(fā)射時(shí),也會(huì)發(fā)射與它相連的信號(hào)B
4.信號(hào)、槽之間的連接可以被移除
disconnect(sender,SIGNAL(signal),receiver,SLOT(slot));
因?yàn)閯h除對(duì)象時(shí),Qt會(huì)自動(dòng)移除和這個(gè)對(duì)象相關(guān)的所有連接,所以這個(gè)語法很少用到。
除此之外,要把信號(hào)成功連接到槽(或者連接到另一個(gè)信號(hào)),還應(yīng)該注意,相連接的信號(hào)和槽必須具有相同順序相同類型的參數(shù),如果信號(hào)的參數(shù)比它所連接的槽的參數(shù)多,那么多余的參數(shù)將被簡單的忽略掉。例如:
connect(sender,SIGNAL(rawCommandReply(int,const QString &)),
receiver,SIGNAL(processReply(int , const QString &)));
如果參數(shù)類型不匹配,或者信號(hào)或槽不存在,盡管應(yīng)用程序調(diào)試構(gòu)建可能會(huì)通過,但Qt會(huì)在運(yùn)行時(shí)發(fā)出警告。
如果信號(hào)和槽的名字中包含了參數(shù)名,也會(huì)發(fā)生錯(cuò)誤警告
實(shí)際上這種機(jī)制是在QObject中實(shí)現(xiàn)的,這表明信號(hào)和槽并不僅僅局限于GUI編程中,實(shí)際上這種機(jī)制可以用于任何QObject的子類中,
在普通的類中使用信號(hào)和槽機(jī)制
Class Circle:public QObject
{
Q_ONJECT
public:
Circle(){CircleRadius=0;}
int Radius(){return CircleRadius;}
public slots:
void setRadius(int newRadius);
signals:
void radiusChanged(int newRadius);
private:
int circleRadius;
};
void Circle::setRadius(int newRadius)
{
if(newRadius!=circleRadius)
{
circleRadius=newRadius;
emit radiusChanged(circleRadius);
}
}
來看一下,setRadius()槽是如何工作的。
仔細(xì)閱讀會(huì)發(fā)現(xiàn)只有在newRadius不等于circleRadius的時(shí)候,才會(huì)發(fā)射radiusChanged()信號(hào)。這樣既可以確保信號(hào)和槽連接又不會(huì)導(dǎo)致無限循環(huán)。
??我的目標(biāo)是:someday,即便你花錢看我的文章,也會(huì)覺得心滿意足