青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

詳解QT 信號機制 (上篇)轉載

Posted on 2011-07-14 07:14 RTY 閱讀(907) 評論(0)  編輯 收藏 引用 所屬分類: QtC/C++轉載隨筆

詳解QT 信號機制 (上篇)

2011-07-05 18:32 佚名 互聯網 我要評論(1) 字號:T | T
一鍵收藏,隨時查看,分享好友!

信號不是Unix中進程間通信的信號。這里的信號更多地與圖形界面的輸入輸出聯系在一起(當然也可以是不可見的操作)。先來看內容。

AD:

QT 信號機制 是本文要介紹的內容,Qt用預編譯器和宏來保證強大的跨平臺能力,信號機制則是其中最精妙之處。本文分析了幾種常見的信號處理機制,然后詳細介紹了Qt的Signal/Slot機制
 
首先要說明,這里所說的信號不是Unix中進程間通信的信號。這里的信號更多地與圖形界面的輸入輸出聯系在一起(當然也可以是不可見的操作)。自從計算機程序從字符界面轉為圖形界面,用戶的輸入一下子變得繁雜和豐富起來,不同的輸入位置、不同的輸入設備、不同的焦點位置、不同的輸入值組合起來構成了許許多多的信號。一下子,這個世界變得五彩繽紛。當前的三大主流操作系統??Windows、Unix和MAC都提供了令人賞心悅目的圖形界面。

雖然它們出自不同公司,自身還有很多分支,但是在圖形操作與管理上還是大致類同的:都有桌面、有圖標,有大大小小規則或不規則的窗口,窗口上有標題、邊框、菜單以及按鈕等各種控件,用戶可以用鍵盤在當前焦點輸入內容,可以用鼠標點擊任意的窗口和控件。就能動性來說,是由用戶主導程序下一步作何操作,而不象字符時代那樣由程序來主導用戶。這也就是所謂的“事件驅動”。在一個事件驅動的系統中,不論是Windows,還是Unix,都脫離不了以下的處理框架:

當某個應用程序收到操作系統發送的事件時,它就要判斷這個事件該由誰處理。處理過程本身又可能引起新的事件發生,這就要告訴操作系統我發出了什么信號。如此這般循環往復,青山之水常流。那么,一個具體的信號究竟是如何觸發與它對應的函數呢?絕大部分的系統都是采用了回調的機制,所謂“回調”其實就是指向某一個函數的指針。

在C語言中函數名其實也是一個指針,因此回調其實是一個指向指針的指針。在不同的開發框架或開發包中,對于回調的實現有著一些細微的差別。初接觸Qt時,我一直在想它是如何處理各種平臺的信號調用。雖然C語言本身是平臺無關的,但具體到某一個操作系統、某一個開發包,信號機制會有些不同。

而信號是面向對象的開發環境中一個很重要的環節,如果要設計一個類庫或程序框架,就必須很好地考慮不同平臺間的差異。接觸了Qt之后,感覺Qt選擇了一條頗具特色的處理途徑??Signals/Slot,中文名暫定為“信號/反應槽”。在Qt的內部設計中,通過信號/反應槽(signals/slot)的使用對回調進行了很好的封裝。為了更好地了解該機制我們先看一下其他幾種常用的信號相關程序。

1.Win32

Win32的程序總是從WinMain開始執行。在WinMain的代碼中,主要功能一般有三個:一是注冊窗口類,二是在屏幕上顯示窗口,三是實現消息環。消息環的作用就是從應用程序隊列中取出操作系統放入的消息,從而實現用戶和程序之間的交互(也包括象定時器之類的非用戶輸入的消息)。應用程序不定期地在消息環中等待消息的到來。如下所示:// 消息環

  1. while(GetMessage(&msg, NULL, 0, 0))  
  2. {  
  3. TranslateMessage(&msg);  
  4. DispatchMessage(&msg);  

這一段程序包括了形成一個標準消息環的三個基本API:GetM essage()、TranslateMessage()和ispatchMessage()

,采用加速鍵和非模式對話框時將相應改變消息環的結構。在Windows中,GetMessage()是多任務的核心。在應用程序的消息隊列中出現一條消息之前,該函數并不返回任何東西。GetMessage()的等待阻塞了當前進程,因而為正在運行的其他應用程序提供了檢查私有消息環的機會。出現一條消息后,GetMessage()將取出該消息,并將信息存儲在一個MSG數據結構中。對于每一條迫使退出消息環、進程終止的消息(WM_QUIT除外),GetMessage()返回TRUE。

通常在消息環后面跟一個返回語句,迫使WinMain()返回系統。緊跟著GetMessage()的TranslateMessage()對msg進行處理并修改該數據塊的內容。DispatchMessage()負責查找應調用哪一個窗口過程,這種選擇是根據msg中hwnd所標識的窗口進行決策。窗口過程對消息進行處理, 完畢后即返回到消息環, 再次執行GetMessage()。如下圖所示:

為了對所關心的消息做出處理,窗口在創建時一定要提供一個消息回調函數,不管該創建過程是顯式調用還是其他API函數隱式生成。用戶在該回調函數中要對每一個關心的消息做出判斷與處理,從C語言的觀點來看,一個窗口過程(回調函數)就是這樣一個函數:接受四個參數,返回一個LRESULT值,一個switch語句在過程內占用了大量的代碼以完成各個行為動作。

2.MFC

雖然直接用Win32 API開發的程序運行效率高、條理分明,但開發起來卻較為復雜,維護工時也耗用較多,因此現在Windows環境中大部分用C++開發的應用程序使用了微軟提供的MFC類庫。它是面向對象設計的,雖然乍一看其編程風格與Win32迥然不同,但那是高度封裝的結果,其內部的實現與Win32沒有區別。

MFC的一個主導設計思想就是程序框架下(CFrameWnd)的視圖/文檔模型,同時定義了許多宏來簡化編程,其消息的傳遞也與宏息息相關(有關MFC的解剖可看侯捷先生的《深入淺出MFC》第二版)。通過使用這些宏,應用程序自身將維護這一張可能為數不菲的消息映射表。對于程序員來說,只需要點擊鼠標就可完成以上的工作,開發效率有了很大的提高。

3.Linux

Linux(包括其他的Unix)和Windows的一個很大不同點在于其圖形界面的管理是與內核分開的,負責圖形操作(還包括鍵盤、鼠標等事件捕獲)的模塊是X Window。請注意,此處的“Window”與微軟的Windows毫無親戚關系。X Window包括三大部分:服務端(XServer)、客戶端(X Client)和協議(X protocol),示意圖如下:我們平時在Linux下開發的有圖形界面的程序一般就是X Window中的客戶端程序,相對應的庫就是X Lib。

X Lib是X Window中最低層的接口庫,相當于微軟Windows中的 API。這個庫封裝了對X protocol的存取,提供了超過610個函數。由于X protocol可以在網絡上傳播,因此X Window中服務器端和客戶端可以不在一臺機器上,這一點和微軟Windows有著很大的區別。對比X Lib與Win32 API的處理方式,可以發現雖然兩者框架不一、風格不一,但在流程處理上都有異曲同工之妙。

4.Qt

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

同時其本身也是類型安全的,任何一個從QObject或其子類繼承的用戶類都可以使用信號與反應槽。信號的作用如同Windows系統中的消息。在Qt中,對于發出信號的對象來說,它并不知道是誰接收了這個信號。這樣的設計可能在某些地方會有些不便,但卻杜絕了緊耦合,于總體設計有利。反應槽是用來接收信號的, 但它實際上也是普通的函數,程序員可以象調用普通函數一樣來調用反應槽。與信號類似的是,反應槽的擁有者也不知道是誰向它發出了信號。

在程序設計過程中,多個信號可以連接至一個反應槽,類似的,一個信號也可以連接至多個反應槽,甚至一個信號可以連接至另一個信號。在Windows中,如果我們需要多個菜單都激發一個函數,一般是先寫一個共用函數,然后在每個菜單的事件中調用此函數。在Qt中如果要實現同樣的功能,就可以把實現部分寫在一個菜單中,然后把其他菜單與這個菜單級聯起來。

雖然信號/反應槽機制有很多優點,使用也很方便,但它也不是沒有缺點。最大的缺點在于要稍微犧牲一點性能。根據Trolltech公司的自測,在CPU為Intel PentiumII 500 Mhz的PC機上,對于一個信號對應一個反應槽的連接來說,一秒鐘可以調用兩百萬次;對于一個信號對應兩個反應槽的連接來說,一秒鐘可以調用一百二十萬次。

這個速度是不經過連接而直接進行回調的速度的十分之一。請注意這里的十分之一速度比是調用速度的比較,而不是一個完整函數執行時間的比較。事實上一般情況下一個函數的總執行時間大部分是在執行部分,只有小部分是在調用部分,因些這個速度是可以接受的。這就象面向對象的編程和早些年的結構化編程相比一樣:程序的執行效率并沒有提高,反而是有所下降的,但現在大家都在用面向對象的方法編寫程序。用一部分執行效率換回開發效率與維護效率是值得的,況且現在已是P4為主流的時代。我們先來看一個簡單的樣例:

  1. class Demo : public QObject  
  2. {  
  3. Q_OBJECT  
  4. public:  
  5. Demo();  
  6. int value() const { return val; };  
  7. public slots:  
  8. void setValue( int );  
  9. signals:  
  10. void valueChanged( int );  
  11. private:  
  12. int val;  
  13. }; 

由樣例可看到,類的定義中有兩個關鍵字slots和signals,還有一個宏Q_OBJECT。在Qt的程序中如果使用了信號與反應槽就必須在類的定義中聲明這個宏,不過如果你聲明了該宏但在程序中并沒有信號與反應槽,對程序也不會有任何影響,所以建議大家在用Qt寫程序時不妨都把這個宏加上。使用slots定義的就是信號的功能實現,即反應槽,例如:

  1. void Demo::setValue( int v )  
  2. {  
  3. if ( v != val ) {  
  4. vval = v;  
  5. emit valueChanged(v);  
  6. }  

這段程序表明當setValue執行時它將釋放出valueChanged這個信號。以下程序示范了不同對象間信號與反應槽的連接。

  1. Demo a, b;  
  2. connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));  
  3. b.setValue( 11 );  
  4. a.setValue( 7Array );  
  5. b.value(); // b的值將是7Array而不是原先設的11 

在以上程序中,一旦信號與反應槽連接,當執行a.setValue(7Array)時就會釋放出一個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++編譯程序更不會報錯。初學者比較容易忽略這一點,往往是程序編好了沒有錯誤,邏輯上也正確,但運行時就是不按自己的意愿出現結果,這時候應檢查一下是不是這方面的疏忽。Qt的設計者之所以要這樣做估計是為了信號與反應槽之間匹配的嚴格性。既然反應槽與常規函數在執行時沒有什么區別,因此它也可以定義成公共反應槽(public slots)、保護反應槽(protected slots)和私有反應槽(private slots)。如果需要,我們也可以把反應槽定義成虛函數以便子類進行不同的實現,這一點是非常有用的。

只討論一下信號與反應槽的使用好象還不過癮,既然Qt的X11 Free版提供了源代碼,我們就進去看一下在QObject中connect的實現。由于Qt是一個跨平臺的開發庫,為了與不同平臺上的編譯器配合,它定義了一個中間類QMetaObject,該類的作用是存放有關信號/反應槽以及對象自身的信息。這個類是Qt內部使用的,用戶不應去使用它。

小結:關于詳解QT 信號機制 (上篇)的內容介紹完了,請繼續閱讀 詳解QT 信號機制 (下篇)

【編輯推薦】

詳解QT 信號機制 (上篇)

2011-07-05 18:32 佚名 互聯網 我要評論(1) 字號:T | T
一鍵收藏,隨時查看,分享好友!

信號不是Unix中進程間通信的信號。這里的信號更多地與圖形界面的輸入輸出聯系在一起(當然也可以是不可見的操作)。先來看內容。

AD:

QT 信號機制 是本文要介紹的內容,Qt用預編譯器和宏來保證強大的跨平臺能力,信號機制則是其中最精妙之處。本文分析了幾種常見的信號處理機制,然后詳細介紹了Qt的Signal/Slot機制
 
首先要說明,這里所說的信號不是Unix中進程間通信的信號。這里的信號更多地與圖形界面的輸入輸出聯系在一起(當然也可以是不可見的操作)。自從計算機程序從字符界面轉為圖形界面,用戶的輸入一下子變得繁雜和豐富起來,不同的輸入位置、不同的輸入設備、不同的焦點位置、不同的輸入值組合起來構成了許許多多的信號。一下子,這個世界變得五彩繽紛。當前的三大主流操作系統??Windows、Unix和MAC都提供了令人賞心悅目的圖形界面。

雖然它們出自不同公司,自身還有很多分支,但是在圖形操作與管理上還是大致類同的:都有桌面、有圖標,有大大小小規則或不規則的窗口,窗口上有標題、邊框、菜單以及按鈕等各種控件,用戶可以用鍵盤在當前焦點輸入內容,可以用鼠標點擊任意的窗口和控件。就能動性來說,是由用戶主導程序下一步作何操作,而不象字符時代那樣由程序來主導用戶。這也就是所謂的“事件驅動”。在一個事件驅動的系統中,不論是Windows,還是Unix,都脫離不了以下的處理框架:

當某個應用程序收到操作系統發送的事件時,它就要判斷這個事件該由誰處理。處理過程本身又可能引起新的事件發生,這就要告訴操作系統我發出了什么信號。如此這般循環往復,青山之水常流。那么,一個具體的信號究竟是如何觸發與它對應的函數呢?絕大部分的系統都是采用了回調的機制,所謂“回調”其實就是指向某一個函數的指針。

在C語言中函數名其實也是一個指針,因此回調其實是一個指向指針的指針。在不同的開發框架或開發包中,對于回調的實現有著一些細微的差別。初接觸Qt時,我一直在想它是如何處理各種平臺的信號調用。雖然C語言本身是平臺無關的,但具體到某一個操作系統、某一個開發包,信號機制會有些不同。

而信號是面向對象的開發環境中一個很重要的環節,如果要設計一個類庫或程序框架,就必須很好地考慮不同平臺間的差異。接觸了Qt之后,感覺Qt選擇了一條頗具特色的處理途徑??Signals/Slot,中文名暫定為“信號/反應槽”。在Qt的內部設計中,通過信號/反應槽(signals/slot)的使用對回調進行了很好的封裝。為了更好地了解該機制我們先看一下其他幾種常用的信號相關程序。

1.Win32

Win32的程序總是從WinMain開始執行。在WinMain的代碼中,主要功能一般有三個:一是注冊窗口類,二是在屏幕上顯示窗口,三是實現消息環。消息環的作用就是從應用程序隊列中取出操作系統放入的消息,從而實現用戶和程序之間的交互(也包括象定時器之類的非用戶輸入的消息)。應用程序不定期地在消息環中等待消息的到來。如下所示:// 消息環

  1. while(GetMessage(&msg, NULL, 0, 0))  
  2. {  
  3. TranslateMessage(&msg);  
  4. DispatchMessage(&msg);  

這一段程序包括了形成一個標準消息環的三個基本API:GetM essage()、TranslateMessage()和ispatchMessage()

,采用加速鍵和非模式對話框時將相應改變消息環的結構。在Windows中,GetMessage()是多任務的核心。在應用程序的消息隊列中出現一條消息之前,該函數并不返回任何東西。GetMessage()的等待阻塞了當前進程,因而為正在運行的其他應用程序提供了檢查私有消息環的機會。出現一條消息后,GetMessage()將取出該消息,并將信息存儲在一個MSG數據結構中。對于每一條迫使退出消息環、進程終止的消息(WM_QUIT除外),GetMessage()返回TRUE。

通常在消息環后面跟一個返回語句,迫使WinMain()返回系統。緊跟著GetMessage()的TranslateMessage()對msg進行處理并修改該數據塊的內容。DispatchMessage()負責查找應調用哪一個窗口過程,這種選擇是根據msg中hwnd所標識的窗口進行決策。窗口過程對消息進行處理, 完畢后即返回到消息環, 再次執行GetMessage()。如下圖所示:

為了對所關心的消息做出處理,窗口在創建時一定要提供一個消息回調函數,不管該創建過程是顯式調用還是其他API函數隱式生成。用戶在該回調函數中要對每一個關心的消息做出判斷與處理,從C語言的觀點來看,一個窗口過程(回調函數)就是這樣一個函數:接受四個參數,返回一個LRESULT值,一個switch語句在過程內占用了大量的代碼以完成各個行為動作。

2.MFC

雖然直接用Win32 API開發的程序運行效率高、條理分明,但開發起來卻較為復雜,維護工時也耗用較多,因此現在Windows環境中大部分用C++開發的應用程序使用了微軟提供的MFC類庫。它是面向對象設計的,雖然乍一看其編程風格與Win32迥然不同,但那是高度封裝的結果,其內部的實現與Win32沒有區別。

MFC的一個主導設計思想就是程序框架下(CFrameWnd)的視圖/文檔模型,同時定義了許多宏來簡化編程,其消息的傳遞也與宏息息相關(有關MFC的解剖可看侯捷先生的《深入淺出MFC》第二版)。通過使用這些宏,應用程序自身將維護這一張可能為數不菲的消息映射表。對于程序員來說,只需要點擊鼠標就可完成以上的工作,開發效率有了很大的提高。

3.Linux

Linux(包括其他的Unix)和Windows的一個很大不同點在于其圖形界面的管理是與內核分開的,負責圖形操作(還包括鍵盤、鼠標等事件捕獲)的模塊是X Window。請注意,此處的“Window”與微軟的Windows毫無親戚關系。X Window包括三大部分:服務端(XServer)、客戶端(X Client)和協議(X protocol),示意圖如下:我們平時在Linux下開發的有圖形界面的程序一般就是X Window中的客戶端程序,相對應的庫就是X Lib。

X Lib是X Window中最低層的接口庫,相當于微軟Windows中的 API。這個庫封裝了對X protocol的存取,提供了超過610個函數。由于X protocol可以在網絡上傳播,因此X Window中服務器端和客戶端可以不在一臺機器上,這一點和微軟Windows有著很大的區別。對比X Lib與Win32 API的處理方式,可以發現雖然兩者框架不一、風格不一,但在流程處理上都有異曲同工之妙。

4.Qt

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

同時其本身也是類型安全的,任何一個從QObject或其子類繼承的用戶類都可以使用信號與反應槽。信號的作用如同Windows系統中的消息。在Qt中,對于發出信號的對象來說,它并不知道是誰接收了這個信號。這樣的設計可能在某些地方會有些不便,但卻杜絕了緊耦合,于總體設計有利。反應槽是用來接收信號的, 但它實際上也是普通的函數,程序員可以象調用普通函數一樣來調用反應槽。與信號類似的是,反應槽的擁有者也不知道是誰向它發出了信號。

在程序設計過程中,多個信號可以連接至一個反應槽,類似的,一個信號也可以連接至多個反應槽,甚至一個信號可以連接至另一個信號。在Windows中,如果我們需要多個菜單都激發一個函數,一般是先寫一個共用函數,然后在每個菜單的事件中調用此函數。在Qt中如果要實現同樣的功能,就可以把實現部分寫在一個菜單中,然后把其他菜單與這個菜單級聯起來。

雖然信號/反應槽機制有很多優點,使用也很方便,但它也不是沒有缺點。最大的缺點在于要稍微犧牲一點性能。根據Trolltech公司的自測,在CPU為Intel PentiumII 500 Mhz的PC機上,對于一個信號對應一個反應槽的連接來說,一秒鐘可以調用兩百萬次;對于一個信號對應兩個反應槽的連接來說,一秒鐘可以調用一百二十萬次。

這個速度是不經過連接而直接進行回調的速度的十分之一。請注意這里的十分之一速度比是調用速度的比較,而不是一個完整函數執行時間的比較。事實上一般情況下一個函數的總執行時間大部分是在執行部分,只有小部分是在調用部分,因些這個速度是可以接受的。這就象面向對象的編程和早些年的結構化編程相比一樣:程序的執行效率并沒有提高,反而是有所下降的,但現在大家都在用面向對象的方法編寫程序。用一部分執行效率換回開發效率與維護效率是值得的,況且現在已是P4為主流的時代。我們先來看一個簡單的樣例:

  1. class Demo : public QObject  
  2. {  
  3. Q_OBJECT  
  4. public:  
  5. Demo();  
  6. int value() const { return val; };  
  7. public slots:  
  8. void setValue( int );  
  9. signals:  
  10. void valueChanged( int );  
  11. private:  
  12. int val;  
  13. }; 

由樣例可看到,類的定義中有兩個關鍵字slots和signals,還有一個宏Q_OBJECT。在Qt的程序中如果使用了信號與反應槽就必須在類的定義中聲明這個宏,不過如果你聲明了該宏但在程序中并沒有信號與反應槽,對程序也不會有任何影響,所以建議大家在用Qt寫程序時不妨都把這個宏加上。使用slots定義的就是信號的功能實現,即反應槽,例如:

  1. void Demo::setValue( int v )  
  2. {  
  3. if ( v != val ) {  
  4. vval = v;  
  5. emit valueChanged(v);  
  6. }  

這段程序表明當setValue執行時它將釋放出valueChanged這個信號。以下程序示范了不同對象間信號與反應槽的連接。

  1. Demo a, b;  
  2. connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int)));  
  3. b.setValue( 11 );  
  4. a.setValue( 7Array );  
  5. b.value(); // b的值將是7Array而不是原先設的11 

在以上程序中,一旦信號與反應槽連接,當執行a.setValue(7Array)時就會釋放出一個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++編譯程序更不會報錯。初學者比較容易忽略這一點,往往是程序編好了沒有錯誤,邏輯上也正確,但運行時就是不按自己的意愿出現結果,這時候應檢查一下是不是這方面的疏忽。Qt的設計者之所以要這樣做估計是為了信號與反應槽之間匹配的嚴格性。既然反應槽與常規函數在執行時沒有什么區別,因此它也可以定義成公共反應槽(public slots)、保護反應槽(protected slots)和私有反應槽(private slots)。如果需要,我們也可以把反應槽定義成虛函數以便子類進行不同的實現,這一點是非常有用的。

只討論一下信號與反應槽的使用好象還不過癮,既然Qt的X11 Free版提供了源代碼,我們就進去看一下在QObject中connect的實現。由于Qt是一個跨平臺的開發庫,為了與不同平臺上的編譯器配合,它定義了一個中間類QMetaObject,該類的作用是存放有關信號/反應槽以及對象自身的信息。這個類是Qt內部使用的,用戶不應去使用它。

小結:關于詳解QT 信號機制 (上篇)的內容介紹完了,請繼續閱讀 詳解QT 信號機制 (下篇)

【編輯推薦】

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲一区尤物| 久久精品官网| 久久se精品一区精品二区| 亚洲免费激情| 日韩午夜电影av| 一本色道久久综合狠狠躁篇怎么玩 | 亚洲欧美激情视频在线观看一区二区三区| 亚洲精品乱码久久久久久黑人 | 国产在线视频欧美| 亚洲国产精品成人va在线观看| 亚洲韩国日本中文字幕| 一区二区三区高清在线| 欧美亚洲视频一区二区| 免费不卡在线视频| 99国产精品一区| 久久久国产一区二区| 欧美精品尤物在线| 国产日韩一区欧美| 一区二区冒白浆视频| 久久久久久久久岛国免费| 91久久久在线| 久久久久久亚洲精品杨幂换脸 | 久久精品国产综合精品| 欧美精品二区| 亚洲精品一线二线三线无人区| 久久午夜电影| 一区二区激情小说| 一区二区三区欧美| 亚洲一区二区三区四区五区黄| 一区二区三区久久| 欧美在线一区二区| 欧美色综合网| 一区二区三区免费观看| 欧美成人免费网站| 亚洲欧美亚洲| 国产精品久久久久9999吃药| 亚洲电影免费观看高清完整版| 亚洲欧美激情视频| 亚洲午夜小视频| 国产精品午夜在线| 久久久精品欧美丰满| 午夜视频一区二区| 国产性色一区二区| 久久久久国产精品厨房| 久久精品国产99| 一区二区视频在线观看| 另类天堂视频在线观看| 欧美福利视频一区| 中文在线资源观看视频网站免费不卡| 亚洲日本成人网| 玖玖精品视频| 亚洲三级电影在线观看| 一区二区免费在线观看| 国产精品看片资源| 久久网站免费| 欧美另类专区| 久久久久看片| 欧美黄色片免费观看| 欧美高清在线观看| 久久久久久久999精品视频| 欧美黄色影院| 欧美www视频| 国产热re99久久6国产精品| 最新日韩在线视频| 狠狠色伊人亚洲综合网站色| 亚洲区免费影片| 影音先锋中文字幕一区| 亚洲影视在线| 亚洲欧美日韩网| 欧美美女福利视频| 欧美激情一区在线| 亚洲欧洲精品一区二区三区| 久久精选视频| 久久综合精品国产一区二区三区| 欧美性生交xxxxx久久久| 亚洲国产精品一区二区尤物区| 亚洲国产精品久久久久秋霞蜜臀| 欧美在线视频不卡| 久久精品视频在线播放| 国产日韩欧美一区| 久久嫩草精品久久久精品一| 久久久久久久一区| **欧美日韩vr在线| 欧美精品久久久久久久| 在线视频欧美一区| 久久精品女人天堂| 在线精品一区二区| 欧美日韩三级电影在线| 午夜综合激情| 最新国产精品拍自在线播放| 亚洲美女黄网| 国产精品一卡二| 久久久久久久久久久成人| 亚洲精品自在久久| 国产精品美女在线观看| 亚洲欧美国产一区二区三区| 免费看成人av| 欧美一级二级三级蜜桃| 亚洲精品五月天| 亚洲成人在线免费| 亚洲欧美日韩精品久久亚洲区| 亚洲一区二区av电影| 免费在线亚洲| 国产精品v欧美精品v日韩| 国产精品一区二区久久久久| 好吊色欧美一区二区三区四区| 模特精品裸拍一区| 午夜精品视频网站| 在线性视频日韩欧美| 欧美激情在线狂野欧美精品| 久久精品视频亚洲| 亚洲欧美伊人| 一区二区三区四区蜜桃| 91久久极品少妇xxxxⅹ软件| 一区二区亚洲| 1024成人网色www| 亚洲第一网站| 亚洲日本成人女熟在线观看| 国产一区二区三区在线观看免费| 国产精品一区久久久久| 国产欧美 在线欧美| 国产欧美日韩不卡免费| 91久久夜色精品国产九色| 午夜精品国产精品大乳美女| 久久精品综合一区| 亚洲国产综合在线| 午夜视频久久久| 老司机一区二区三区| 欧美ed2k| 激情丁香综合| 亚洲欧美日韩在线不卡| 欧美成人免费大片| 激情久久久久久久| 99视频一区二区| 亚洲高清不卡在线观看| 亚洲黄色在线视频| 久久精品国产亚洲高清剧情介绍| 日韩视频免费观看高清在线视频 | 精品电影一区| 亚洲欧美电影院| 亚洲国产日韩在线| 亚洲精品国偷自产在线99热| 欧美风情在线观看| 国产精品久久午夜| 欧美高清自拍一区| 国产日韩三区| 91久久精品国产91久久性色| 免费观看成人| 亚洲无毛电影| 久久国产精品久久久久久久久久 | 国产精品区一区二区三| 亚洲婷婷在线| 亚洲欧美影院| 怡红院av一区二区三区| 欧美福利视频| 欧美国产免费| 在线视频欧美一区| 性刺激综合网| 91久久黄色| 亚洲男女自偷自拍| 亚洲品质自拍| 久久先锋资源| 久久综合精品一区| 欧美性色视频在线| 毛片av中文字幕一区二区| 欧美视频一区二区| 亚洲人在线视频| 亚洲电影免费观看高清完整版在线观看 | 亚洲欧美成人网| 亚洲电影专区| 亚洲色图在线视频| 91久久精品国产91久久性色tv | 久久亚洲欧洲| 欧美午夜激情视频| 亚洲人成啪啪网站| 在线欧美不卡| 久久精品国产一区二区三| 亚洲欧美春色| 国产精品99一区| 亚洲精品日韩久久| 亚洲国产片色| 欧美日韩国产成人在线| 亚洲精选大片| 欧美在线观看天堂一区二区三区| 国产精品欧美日韩一区二区| 欧美一区日韩一区| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美成人午夜激情| 国产精品激情偷乱一区二区∴| 老牛嫩草一区二区三区日本| 国产精品福利网| 亚洲高清123| 国产精品伦一区| 亚洲欧美电影在线观看| 亚洲影院免费| 国产精品夜夜夜一区二区三区尤| 91久久久亚洲精品| 亚洲午夜激情免费视频| 欧美国产日韩一二三区| 一本久久知道综合久久|