QT中關鍵字講解(emit,signal,slot)

轉載:https://www.cnblogs.com/felix-wang/p/6212197.html請見原文

Qt中的類庫有接近一半是從基類QObject上繼承下來,信號與反應槽(signals/slot)機制就是用來在QObject類或其子類間通訊的方法。作爲一種通用的處理機制,信號與反應槽非常靈活,可以攜帶任意數量的參數,參數的類型也由用戶自定。同時其本身也是類型安全的,任何一個從QObject或其子類繼承的用戶類都可以使用信號與反應槽。

由樣例可看到,**類的定義中有兩個關鍵字slots和signals,還有一個宏Q_OBJECT。**在Qt的程序中如果使用了信號與反應槽就必須在類的定義中聲明這個宏,不過如果你聲明瞭該宏但在程序中並沒有信號與反應槽,對程序也不會有任何影響,所以建議大家在用Qt寫程序時不妨都把這個宏加上。
在這裏插入圖片描述
在以上程序中,一旦信號與反應槽連接,當執行a.setValue(79)時就會釋放出一個valueChanged(int)的信號,對象b將會收到這個信號並觸發setValue(int)這個函數。當b在執行setValue(int)這個函數時,它也將釋放valueChanged(int)這個信號,當然b的信號無人接收,因此就什麼也沒幹。請注意,在樣例中我們僅當輸入變量v不等於val時才釋放信號,因此就算對a與b進行了交叉連接也不會導致死循環的發生。由於在樣例中使用了Qt特有的關鍵字和宏,而Qt本身並不包括C++的編譯器,因此如果用流行的編譯程序(如Windows下的Visual C++或Linux下的gcc)是不能直接編譯這段代碼的,必須用Qt的中間編譯工具moc.exe把該段代碼轉換爲無專用關鍵字和宏的C++代碼才能爲這些編譯程序所解析、編譯與鏈接。

以上代碼中信號與反應槽的定義是在類中實現的。那麼,非類成員的函數,比如說一個全局函數可不可以也這樣做呢?答案是不行,只有是自身定義了信號的類或其子類纔可以發出該種信號。一個對象的不同信號可以連接至不同的對象。當一個信號被釋放時,與之連接的反應槽將被立刻執行,就象是在程序中直接調用該函數一樣。信號的釋放過程是阻塞的,這意味着只有當反應槽執行完畢後該信號釋放過程才返回。如果一個信號與多個反應槽連接,則這些反應槽將被順序執行,排序過程則是任意的。因此如果程序中對這些反應槽的先後執行次序有嚴格要求的,應特別注意。使用信號時還應注意:信號的定義過程是在類的定義過程即頭文件中實現的。

爲了中間編譯工具moc的正常運行,不要在源文件(.cpp)中定義信號,

同時信號本身不應返回任何數據類型,即是空值(void)。如果你要設計一個通用的類或控件,則在信號或反應槽的參數中應儘可能使用常規數據以增加通用性。如上例代碼中valueChanged的參數爲int型,如果它使用了特殊類型如QRangeControl::Range,那麼這種信號只能與RangeControl中的反應槽連接。如前所述,反應槽也是常規函數,與未定義slots的用戶函數在執行上沒有任何區別。

**但在程序中不可把信號與常規函數連接在一起,否則信號的釋放不會引起對應函數的執行。**要命的是中間編譯程序moc並不會對此種情況報錯,C++編譯程序更不會報錯。初學者比較容易忽略這一點,往往是程序編好了沒有錯誤,邏輯上也正確,但運行時就是不按自己的意願出現結果,這時候應檢查一下是不是這方面的疏忽。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章