![QT信號與槽的無敵教程_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/17/ba913739-648d-4e3b-8577-69860f8ac4f9/ba913739-648d-4e3b-8577-69860f8ac4f91.gif)
![QT信號與槽的無敵教程_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/17/ba913739-648d-4e3b-8577-69860f8ac4f9/ba913739-648d-4e3b-8577-69860f8ac4f92.gif)
![QT信號與槽的無敵教程_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/17/ba913739-648d-4e3b-8577-69860f8ac4f9/ba913739-648d-4e3b-8577-69860f8ac4f93.gif)
![QT信號與槽的無敵教程_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/17/ba913739-648d-4e3b-8577-69860f8ac4f9/ba913739-648d-4e3b-8577-69860f8ac4f94.gif)
![QT信號與槽的無敵教程_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-2/17/ba913739-648d-4e3b-8577-69860f8ac4f9/ba913739-648d-4e3b-8577-69860f8ac4f95.gif)
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、一、概述二、信號三、槽四、信號和槽的關聯(lián)五、元對象工具六、程式樣例七、應注意的問題 相關資源 作者簡介 作者 : 唐新華 (xhsmart) 軟件工程師 信號和槽作為 QT 的核心機制在 QT 編程中有著廣泛的應用, 本文介紹了信號和槽的一些基 本概念、元對象工具及在實際使用過程中應注意的一些問題。QT 是個跨平臺的 C+ GUI 應用構架,他提供了豐富的窗口部件集,具有面向對象、易于 擴展、真正的組件編程等特點,更為引人注目的是目前 Linux 上最為流行的 KDE 桌面環(huán)境 就是建立在 QT 庫的基礎之上。 QT 支持下列平臺: MS/WINDOWS-95 、 98、NT 和 2000;
2、UNIX/X11-Linux 、Sun Solaris、HP-UX 、Digital Unix 、IBM AIX 、SGI IRIX ;EMBEDDED- 支持 framebuffer 的 Linux 平臺。伴隨著 KDE 的快速發(fā)展和普及, QT 非??赡艹蔀?Linux 窗口平臺上進行軟件研發(fā)時的 GUI 最佳選擇。一、概述 信號和槽機制是 QT 的核心機制,要精通 QT 編程就必須對信號和槽有所了解。信號和槽是 一種高級接口,應用于對象之間的通信,他是 QT 的核心特性,也是 QT 差別于其他工具包 的重要地方。信號和槽是 QT 自行定義的一種通信機制,他獨立于標準的C/C+ 語言,因此
3、要正確的處理信號和槽,必須借助一個稱為moc( Meta Object Compiler )的 QT 工具,該工具是個 C+ 預處理程式,他為高層次的事件處理自動生成所需要的附加代碼。 在我們所熟知的非常多 GUI 工具包中, 窗口小部件 (widget) 都有一個回調函數(shù)用于響應他們 能觸發(fā)的每個動作,這個回調函數(shù)通常是個指向某個函數(shù)的指針。不過,在 QT 中信號和 槽取代了這些凌亂的函數(shù)指針, 使得我們編寫這些通信程式更為簡潔明了。 信號和槽能攜帶 任意數(shù)量和任意類型的參數(shù), 他們是類型完全安全的, 不會像回調函數(shù)那樣產生 core dumps。 所有從 QObject 或其子類 (例如
4、Qwidget) 派生的類都能夠包含信號和槽。當對象改動其狀態(tài) 時,信號就由該對象發(fā)射 (emit) 出去,這就是對象所要做的全部事情,他不知道另一端是誰 在接收這個信號。這就是真正的信息封裝,他確保對象被當作一個真正的軟件組件來使用。 槽用于接收信號, 但他們是普通的對象成員函數(shù)。 一個槽并不知道是否有所有信號和自己相 連接。而且,對象并不了解具體的通信機制。你能將非常多信號和單個的槽進行連接, 也能將單個的信號和非常多的槽進行連接, 甚至于 將一個信號和另外一個信號相連接也是可能的, 這時無論第一個信號什么時候發(fā)射系統(tǒng)都將 即時發(fā)射第二個信號??傊?,信號和槽構造了一個強大的部件編程機制。二
5、、信號 當某個信號對其客戶或所有者發(fā)生的內部狀態(tài)發(fā)生改動, 信號被一個對象發(fā)射。 只有定義過 這個信號的類及其派生類能夠發(fā)射這個信號。 當一個信號被發(fā)射時, 和其相關聯(lián)的槽將被即 時執(zhí)行,就象一個正常的函數(shù)調用相同。信號 -槽機制完全獨立于所有 GUI 事件循環(huán)。只有 當所有的槽返回以后發(fā)射函數(shù)( emit )才返回。如果存在多個槽和某個信號相關聯(lián),那么, 當這個信號被發(fā)射時,這些槽將會一個接一個地執(zhí)行,不過他們執(zhí)行的順序將會是隨機的、 不確定的,我們不能人為地指定哪個先執(zhí)行、哪個后執(zhí)行。信號的聲明是在頭文件中進行的, QT 的 signals 關鍵字指出進入了信號聲明區(qū), 隨后即可聲 明自己
6、的信號。例如,下面定義了三個信號:signals:void mySignal();void mySignal(int x);void mySignalParam(int x,int y);在上面的定義中,signals是QT的關鍵字,而非C/C+的。接下來的一行 void mySignal() 定 義了信號 mySignal ,這個信號沒有攜帶參數(shù);接下來的一行 void mySignal(int x) 定義了重名 信號mySignal,不過他攜帶一個整形參數(shù),這有點類似于C+中的虛函數(shù)。從形式上講信號的聲明和普通的C+函數(shù)是相同的,不過信號卻沒有函數(shù)體定義,另外,信號的返回類型都是void,
7、不要指望能從信號返回什么有用信息。信號由 moc 自動產生,他們不應該在 .cpp 文件中實現(xiàn)。三、槽槽是普通的C+成員函數(shù),能被正常調用,他們唯一的特別性就是非常多信號能和其相關聯(lián)。 當和其關聯(lián)的信號被發(fā)射時,這個槽就會被調用。槽能有參數(shù),但槽的參數(shù)不能有缺省值。 既然槽是普通的成員函數(shù), 因此和其他的函數(shù)相同, 他們也有存取權限。 槽的存取權限決定 了誰能夠和其相關聯(lián)。同普通的C+成員函數(shù)相同,槽函數(shù)也分為三種類型,即public slots、private slots 和 protected slots。public slots :在這個區(qū)內聲明的槽意味著所有對象都可將信號和之相連接。這
8、對于組件編程 非常有用, 你能創(chuàng)建彼此互不了解的對象, 將他們的信號和槽進行連接以便信息能夠正確的 傳遞。protected slots:在這個區(qū)內聲明的槽意味著當前類及其子類能將信號和之相連接。這適用于那些槽,他們是類實現(xiàn)的一部分,不過其界面接口卻面向外部。private slots :在這個區(qū)內聲明的槽意味著只有類自己能將信號和之相連接。這適用于聯(lián)系非常緊密的類。槽也能夠聲明為虛函數(shù),這也是非常有用的。 槽的聲明也是在頭文件中進行的。例如,下面聲明了三個槽:public slots: void mySlot();void mySlot(int x);void mySignalParam(i
9、nt x,int y);四、信號和槽的關聯(lián)通過調用QObject對象的connect函數(shù)來將某個對象的信號和另外一個對象的槽函數(shù)相關聯(lián), 這樣當發(fā)射者發(fā)射信號時,接收者的槽函數(shù)將被調用。該函數(shù)的定義如下:bool QObject:connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * member ) static 這個函數(shù)的作用就是將發(fā)射者sender對象中的信號signal和接收者receiver中的member槽函數(shù)聯(lián)系起來。當指定信號 signal 時必須
10、使用 QT 的宏 SIGNAL() ,當指定槽函數(shù)時必須使 用宏SLOT()。如果發(fā)射者和接收者屬于同一個對象的話,那么在connect調用中接收者參數(shù)能省略。例如,下面定義了兩個對象:標簽對象 label和滾動條對象scroll,并將valueChanged()信號 和標簽對象的setNum()相關聯(lián),另外信號還攜帶了一個整形參數(shù),這樣標簽總是顯示滾動條所處位置的值。QLabel *label = new QLabel;QScrollBar *scroll = new QScrollBar;QObject:connect( scroll, SIGNAL(valueChanged(int),l
11、abel, SLOT(setNum(int) );一個信號甚至能夠和另一個信號相關聯(lián),看下面的例子:class MyWidget : public QWidgetpublic:MyWidget();signals:void aSignal();private:QPushButton *aButton;MyWidget:MyWidget()aButton = new QPushButton( this );connect( aButton, SIGNAL(clicked(), SIGNAL(aSignal() );在上面的構造函數(shù)中,MyWidget創(chuàng)建了一個私有的按鈕aButton,按鈕的單擊
12、事件產生的信號clicked。和另外一個信號 aSignal()進行了關聯(lián)。這樣一來,當信號clicked。被發(fā)射時,信 號aSignal()也接著被發(fā)射。當然,你也能直接將單擊事件和某個私有的槽函數(shù)相關聯(lián),然后在槽中發(fā)射aSignal()信號,這樣的話似乎有點多余。當信號和槽沒有必要繼續(xù)保持關聯(lián)時, 我們能使用 disconnect 函數(shù)來斷開連接。其定義如下: bool QObject:disconnect ( const QObject * sender, const char * signal,const Object * receiver, const char * member )
13、 static 這個函數(shù)斷研發(fā)射者中的信號和接收者中的槽函數(shù)之間的關聯(lián)。有三種情況必須使用 disco nn ect()函數(shù):斷開和某個對象相關聯(lián)的所有對象。 這似乎有點不可理解, 事實上,當我們在某個對象中定 義了一個或多個信號, 這些信號和另外若干個對象中的槽相關聯(lián), 如果我們要切斷這些關聯(lián) 的話,就能利用這個方法,非常之簡潔。disconnect( myObject, 0, 0, 0 )或myObject->disconnect()斷開和某個特定信號的所有關聯(lián)。disconnect( myObject, SIGNAL(mySignal(), 0, 0 )或myObject->
14、disconnect( SIGNAL(mySignal() )斷開兩個對象之間的關聯(lián)。disconnect( myObject, 0, myReceiver, 0 )或myObject->disconnect( myReceiver ) 在 disconnect 函數(shù)中 0 能用作一個通配符,分別表示所有信號、所有接收對象、接收對象中的所有槽函數(shù)。不過發(fā)射者sender不能為0,其他三個參數(shù)的值能等于0。五、元對象工具元對象編譯器 moc( meta object compiler )對C+文件中的類聲明進行分析并產生用于初始 化元對象的C+代碼,元對象包含全部信號和槽的名字及指向這些函
15、數(shù)的指針。moc讀C+源文件,如果發(fā)現(xiàn)有Q_OBJECT宏聲明的類,他就會生成另外一個 C+源文件, 這個新生成的文件中包含有該類的元對象代碼。例如,假設我們有一個頭文件mysignal.h ,在這個文件中包含有信號或槽的聲明, 那么在編譯之前 moc 工具就會根據該文件自動生成 一個名為mysignal.moc.h的C+源文件并將其提交給編譯器;類似地,對應于mysignal.cpp文件 moc 工具將自動生成一個名為 mysignal.moc.cpp 文件提交給編譯器。元對象代碼是signal/slot機制所必須的。用moc產生的C+源文件必須和類實現(xiàn)一起進行編 譯和連接,或用#inclu
16、de語句將其包含到類的源文件中。moc并不擴展#include或#define宏定義,他只是簡單的跳過所遇見的所有預處理指令。六、程式樣例這里給出了一個簡單的樣例程式, 程式中定義了三個信號、 三個槽函數(shù),然后將信號和槽進 行了關聯(lián),每個槽函數(shù)只是簡單的彈出一個對話框窗口。讀者能用kdevelop 生成一個簡單的 QT 應用程式,然后將下面的代碼添加到相應的程式中去。信號和槽函數(shù)的聲明一般位于頭文件中,同時在類聲明的開始位置必須加上Q_OBJECT 語句,這條語句是不可缺少的,他將告訴編譯器在編譯之前必須先應用moc 工具進行擴展。關鍵字signals指出隨后開始信號的聲明,這里signals
17、用的是復數(shù)形式而非單數(shù),siganls沒有 public、 private、protected 等屬性,這點不同于slots。另外,signals、slots 關鍵字是 QT自己定義的,不是 C+中的關鍵字。信號的聲明類似于函數(shù)的聲明而非變量的聲明, 左邊要有類型,右邊要有括號,如果要向槽 中傳遞參數(shù)的話,在括號中指定每個形式參數(shù)的類型,當然,形式參數(shù)的個數(shù)能多于一個。關鍵字slots指出隨后開始槽的聲明,這里slots用的也是復數(shù)形式。槽的聲明和普通函數(shù)的聲明相同,能攜帶零或多個形式參數(shù)。既然信號的聲明類似于普通 C+函數(shù)的聲明,那么,信號也可采用 C+中虛函數(shù)的形式進行聲明,即同名但參數(shù)不
18、同。 例如,第一次定義的 void mySignal() 沒有帶參數(shù),而第二次定義的卻帶有參數(shù),從這里我們 能看到 QT 的信號機制是非常靈活的。信號和槽之間的聯(lián)系必須事先用conn ect函數(shù)進行指定。如果要斷開二者之間的聯(lián)系,能使用函數(shù) disconnect。/tsignal.h class TsignalApp:public QMainWindowQ_OBJECT/信號聲明區(qū)signals:/聲明信號 mySignal()void mySignal();/聲明信號 mySignal(int)void mySignal(int x);/聲明信號 mySignalParam(int,int)
19、void mySignalParam(int x,int y);/槽聲明區(qū)public slots:/聲明槽函數(shù) mySlot()void mySlot();/聲明槽函數(shù) mySlot(int)void mySlot(int x);/聲明槽函數(shù) mySignalParam (int ,int)void mySignalParam(int x,int y);/tsignal.cppTsignalApp:TsignalApp()將信號mySignal()和槽mySlot()相關聯(lián) connect(this,SIGNAL(mySignal(),SLOT(mySlot();/將信號 mySignal(
20、int) 和槽 mySlot(int) 相關聯(lián) connect(this,SIGNAL(mySignal(int),SLOT(mySlot(int);/將信號 mySignalParam(int,int) 和槽 mySlotParam(int,int) 相關聯(lián) connect(this,SIGNAL(mySignalParam(int,int),SLOT(mySlotParam(int,int);/ 定義槽函數(shù) mySlot()void TsignalApp:mySlot()QMessageBox:about(this, ”Tsignal ”, “This is a signal/slot s
21、ample withoutparameter. ”);/ 定義槽函數(shù) mySlot(int)void TsignalApp:mySlot(int x)QMessageBox:about(this, ”Tsignal ”, “This is a signal/slot sample with one parameter. ”);/ 定義槽函數(shù) mySlotParam(int,int)void TsignalApp:mySlotParam(int x,int y)char s256;sprintf(s, ”x:%d y:%d ”,x,y);QMessageBox:about(this, ”Tsig
22、nal ”, s);void TsignalApp:slotFileNew()/發(fā)射信號 mySignal()emit mySignal();/發(fā)射信號 mySignal(int)emit mySignal(5);/發(fā)射信號 mySignalParam(5 ,100)emit mySignalParam(5,100);七、應注意的問題信號和槽機制是比較靈活的, 但有些局限性我們必須了解, 這樣在實際的使用過程中做到有 的放矢,避免產生一些錯誤。下面就介紹一下這方面的情況。1信號和槽的效率是非常高的,不過同真正的回調函數(shù)比較起來,由于增加了靈活性,因 此在速度上還是有所損失,當然這種損失相對來說
23、是比較小的,通過在一臺 i586-133 的機 器上測試是 10 微秒(運行 Linux ),可見這種機制所提供的簡潔性、靈活性還是值得的。但 如果我們要追求高效率的話,比如在實時系統(tǒng)中就要盡可能的少用這種機制。2信號和槽機制和普通函數(shù)的調用相同,如果使用不當?shù)脑?,在程式?zhí)行時也有可能產生 死循環(huán)。 因此, 在定義槽函數(shù)時一定要注意避免間接形成無限循環(huán), 即在槽中再次發(fā)射所接 收到的同樣信號。例如, 在前面給出的例子中如果在mySlot() 槽函數(shù)中加上語句 emitmySignal() 即可形成死循環(huán)。3如果一個信號和多個槽相聯(lián)系的話,那么,當這個信號被發(fā)射時,和之相關的槽被激活 的順序將是
24、隨機的。4. 宏定義不能用在 signal 和 slot 的參數(shù)中。既然moc工具不擴展#define,因此,在signals和slots中攜帶參數(shù)的宏就不能正確地工作, 如果不帶參數(shù)是能的。例如,下面的例子中將帶有參數(shù)的宏 SIGNEDNESS(a) 作為信號的參 數(shù)是不合語法的:#ifdef ultrix#define SIGNEDNESS(a) unsigned a#else#define SIGNEDNESS(a) a#endifclass Whatever : public QObjectsignals:void someSignal( SIGNEDNESS(a) );5. 構造函數(shù)
25、不能用在 signals 或 slots 聲明區(qū)域內。的確,將一個構造函數(shù)放在 signals 或 slots 區(qū)內有點不可理解,無論怎么,不能將他們放在private slots、protected slots 或 public slots 區(qū)內。下面的用法是不合語法需求的:class SomeClass : public QObjectQ_OBJECTpublic slots:SomeClass( QObject *parent, const char *name ): QObject( parent, name ) / 在槽聲明區(qū)內聲明構造函數(shù)不合語法;6. 函數(shù)指針不能作為信號或槽的參
26、數(shù)。 例如,下面的例子中將 void (*applyFunction)(QList*, void*) 作為參數(shù)是不合語法的: class someClass : public QObjectQ_OBJECTpublic slots:void apply(void (*applyFunction)(QList*, void*), char*); /不合語法; 你能采用下面的方法繞過這個限制: typedef void (*ApplyFunctionType)(QList*, void*); class someClass : public QObjectQ_OBJECTpublic slots:void apply( ApplyFunctionType, char *);7. 信號和槽不能有缺省參數(shù)。既然 signal->slot 綁定是發(fā)生在運行時刻,那么,從概念上講使用缺省參數(shù)是
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 未來就業(yè)市場的變化及職業(yè)定位分析
- 現(xiàn)代建筑設計與智能化技術的融合實踐
- 生態(tài)文明產業(yè)園的教育培訓與人才培養(yǎng)策略
- 團委國慶節(jié)觀影活動方案
- 術后康復神經外科手術患者的居家照護
- Unit 2 Wildlife Protection Reading and Thinking 第二課時說課稿-2024-2025學年高一英語人教版(2019)必修第二冊
- 2024秋八年級歷史上冊 第一單元 中國開始淪為半殖民地半封建社會 第3課 太平天國運動說課稿 新人教版001
- 2024年五年級英語上冊 Unit 6 My e-friend第1課時說課稿 牛津譯林版
- 《100 以內的加法和減法(二)-進位加》(說課稿)-2024-2025學年二年級上冊數(shù)學人教版001
- 2024年一年級品生下冊《春天在哪里》說課稿 山東版
- 抖音麗人行業(yè)短視頻直播項目運營策劃方案
- 精神病服藥訓練
- (2024年)知識產權全套課件(完整)
- 2024-2030年中國城市軌道交通行業(yè)發(fā)展現(xiàn)狀分析及市場供需預測報告
- 預防靜脈血栓疾病知識講座
- 《社區(qū)康復》課件-第十一章 其他疾病的社區(qū)康復實踐
- 2024年專升本考試-專升本考試(機械設計基礎)筆試歷年真題薈萃含答案
- 藥物過量的護理查房
- 部編版五年級語文下冊第七單元大單元教學設計
- 松茸推廣引流方案
- 項目式學習:教師手冊
評論
0/150
提交評論