Qt學習筆記-Qt概念解析
(1)訊號和槽機制(Signal&Slot)
Qt提供了訊號和槽機制用於完成介面操作的響應,是完成兩個任意Qt物件之間的通訊機制。其中,訊號會在某個特定情況或動作下被觸發,槽是等同於接受並處理訊號的函式。例如,若要將一個視窗部件的變化情況通知給另一個視窗部件,則一個視窗部件傳送訊號,另一個視窗部件的槽接受此訊號並進行相應的操作,即可實現兩個視窗部件之間的通訊。每個Qt物件都包含若干個預定義的訊號和若干個預定義的槽,當某一個特定事件發生時,一個訊號被髮射,與訊號相關聯的槽則會響應訊號並完成相應的處理。當一個類被繼承時,該類的訊號和槽也同時被繼承,也可以根據需要自定義訊號和槽。
1)訊號和槽的連線方式
<1>一個訊號可以與另一個訊號相連,程式碼如下:
connect(Object1,SIGNAL(signal1),Object2,SIGNAL(signal2));
表示Object1的訊號1發射可以觸發Object2的訊號1發射
<2>同一個訊號可以和多個槽相連,程式碼如下:
connect(Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
connect(Object1,SIGNAL(signal2),Object3,SIGNAL(slot1));
<3>同一個槽可以響應多個訊號,程式碼如下
connect(Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
connect(Object3,SIGNAL(signal2),Object3,SIGNAL(slot2));
但是常用的連線方式是:
connect(Object1,SIGNAL(signal),Object2,SLOT(slot));
其中,signal為物件Object1的訊號,slot為物件Object2的槽
SIGNAL()和SLOT()是Qt中定義的兩個巨集,他們返回其引數的C語言風格的字串(const char *)。因此,下面關聯訊號和槽的連個語句是等同的:
connect(button,SIGNAL(clicked()),this,SLOT(showArea));
connect(button,"clicked()",this,"showArea");
(2)訊號和槽機制的優點
1)型別安全。需要關聯的訊號和槽的簽名必須是等同的,即訊號的引數型別和引數個數同接收該訊號的槽的引數型別和引數個數相同。不過,一個槽的引數個數是可以少於訊號的引數個數的,但缺少的引數必須四訊號引數的最後一個或幾個引數。如果訊號和引數的簽名不符,編譯器就會報錯。
2)鬆散耦合。訊號和槽機制減弱了Qt物件的耦合度。激發新號的Qt物件無需知道是哪個物件的哪個槽需要接收它發出的訊號,它只需要做的是在適合的時間傳送適當的訊號就可以了,而不需要知道也不用關心它的訊號有沒有被接收到,更不需要知道是哪個物件,哪個槽接受到了訊號。同樣的,物件的槽也不知道是哪些訊號關聯了自己,而一旦關聯訊號和槽,Qt就保證了適合的槽得到了呼叫。即使關聯的物件在執行時被刪除,應用程式也不會崩潰。
一個類若要支援訊號和槽,就必須從QObject或QObject的子類繼承。注意,Qt訊號和槽機制不支援對模板的使用。
3)訊號和槽機制的效率
訊號和槽機制增強了物件間通訊的靈活性,然而這也損失了一些效能。同回撥函式相比,訊號和槽機制執行速度有些慢。通常,通過傳遞一個訊號來呼叫槽函式將會比直接呼叫非虛擬函式執行速度慢10倍。原因主要如下:
<1>需要定位接受訊號的物件
<2>安全的遍歷所有的關聯(如一個訊號關聯多個槽的情況)
<3>編組(marshal)/解組(unmarshal)傳遞的引數。
<4>多執行緒的時候,訊號可能需要排隊等待。
然而,與建立堆物件的new操作及刪除堆物件的delete操作相比,訊號和槽的執行代價只是它們很少的一部分。訊號和槽機制導致的這點效能損耗,對實時應用程式是可以忽略的;同訊號和槽提供的靈活性和簡便性相比,這點效能的損失也是值得的。