Qt自定義事件的實現(轉)

原文:http://blog.csdn.net/michealtx/article/details/6866094html

初學Qt,用了Qt自帶的事件,而後想怎麼才能定義本身的事件呢?又如何使用自定義事件呢?看了篇文章,說先要子類化QEvent,而後定義本身的QEvent::Type,而後重寫QWidget::event()函數,而後就能夠調用QCoreApplication::sendEvent()或者QCoreApplication:;postEvent()發送事件就行了。但我比較笨,仍是雲山霧罩,不知道怎麼下手。java

怎麼子類化QEvent?在哪裏定義本身的QEvent::Type?在哪裏重寫QWidget::event()函數?在哪裏調用QCoreApplication::sendEvent()或者QCoreApplication:;postEvent()發送事件?函數

在百度裏搜索開了篇文章對我有啓發http://bluemask.net/p/1215/ ,在google中搜索how to subclass QEvent也搜到一篇對我有啓發的http://www.java2s.com/Code/Cpp/Qt/SubclassQEvent.htm 。(google的英文搜索真不錯!)post

後來我就想,那Qt的發明人是怎麼定義事件的呢?其實站在Qt發明人的角度,QEvent就是他們的「自定義事件」!Ok!這就好辦了!看看Qt發明人怎麼定義的QEvent,看看他們怎麼用本身定義的QEvent,不就回答了文章開頭的倆問題了嘛!O(∩_∩)O~ui

我把整個過程總結爲「長官定義事件」----->「信使傳遞事件」---->「軍隊接收並響應事件」。google

我經過Qt Assistant查找那些與事件相關的類,總結以下:spa

 

一、Qt中定義事件的長官:QEvent

 

QEvent的任務就是定義一些事件類型Type,它們都定義在了一個enum裏。這就是教程中告訴咱們的要子類化QEvent,派生出MyEvent,而後在MyEvent中定義事件類型QEvent::Type。.net

咱們子類化的時候模仿一個QEvent就行了,並且是繼承,好些都不用子類作了,看一下QEvent類中的成員變量和成員函數,就這些東西:htm

好了,咱們經過子類化QEvent,把派生出來的MyEvent看作長官,它定義了具體某個事件。下面看誰是信使。blog

 

二、Qt中傳遞事件的信使:QCoreApplication(QApplication繼承自QCoreApplication)

咱們看看QCoreApplication中定義的一些函數,這些函數就是咱們常常遇到的那些與傳遞事件和過濾事件有關的函數,見下圖:

Public Functions:

 

Static Public Members:

 

因此,到這裏咱們就能夠明確了,你要用QCoreApplication的static public類型的函數入sendEvent或postEvent函數來傳遞送信,要注意:當使用sendEvent時,你的事件要在棧上創建,sendEvent會直接調用notify把事件傳遞給士兵,不走事件隊列;而用postEvent時,你的事件要在堆上創建,即要用new來建立,postEvent會把你的事件追加進事件隊列(詳細過程請看http://blog.csdn.net/michealtx/article/details/6865891)。你還能夠經過重載notify來影響送信過程。

三、Qt中接收響應事件的軍隊:QWidget(這是Qt中的widget之母,諸如QMainWindow、QPushBUtton等等都是繼承自QWidget)

咱們看看QWidget中與事件有關的成員:

看到了嗎?這些就是event handler,即事件處理函數,這是幹活的那幫人。裏面有咱們熟悉的mousePressEvent()、keyPressEvent()等經常使用的事件處理函數,它們都是protected virtual 類型的,能夠重載。因此呀,咱們能夠子類化QWidget,從而繼承獲得好些個event handler,固然也能夠本身定義event handler!至關於本身創造士兵來響應事件。經過山寨QWidget,就能夠創造本身的軍隊!

還有一點就是,當事件到達軍隊的時候,要先審查再分發,審查就是要通過事件過濾,分發就是經過對通過審查的事件進行判斷再把它分給那個相應的士兵這就又涉及到一個類QObject,這是Qt的萬類之母,這個類中有兩個函數一個是eventFilter(),另外一個是event()。要先子類化QObject來建立一個監控者,這個監控者重載eventFilter(),來爲軍隊過濾事件。而後還要在軍隊(QWidget)經過調用installEventFilter ( QObject * filterObj )來安裝過濾器,參數中的filterOb即爲監控者。最後在軍隊(QWidget)中重載event()來分發事件,把事件分給對應會幹這個活的士兵(event handler)。

 

好了,我理解的大致過程就是這樣,我是Qt新手,可能有錯的地方,但願路過的大牛能給與指正,我將不勝感激!

 

什麼話也不如來個例程給力!:

我創建的是Qt Console Application,工程叫MyEvent,下面是main.cpp中的代碼:

 

[cpp]  view plain copy
 
  1.   
[cpp]  view plain copy
 
  1. #include <QtGui/QApplication>  
  2. #include <QCoreApplication>  
  3. #include <QEvent>  
  4. #include <QObject>  
  5. #include <QDebug>  
  6.   
  7. static const QEvent::Type MyEventType = (QEvent::Type)QEvent::registerEventType(QEvent::User+100);  
  8.   
  9. //長官  
  10. class MyEvent: public QEvent  
  11. {  
  12. public:  
  13.     MyEvent(Type MyEventType):QEvent(MyEventType){}  
  14. };  
  15.   
  16. //信使  
  17. class MySender: public QCoreApplication  
  18. {  
  19. public:  
  20.     MySender(int argc,char *argv[]):QCoreApplication(argc,argv){}  
  21.   
  22. public:  
  23.     bool notify(QObject *receiver, QEvent *event);  
  24.   
  25. };  
  26.   
  27. bool MySender::notify(QObject *receiver, QEvent *event)  
  28. {  
  29.     if(event->type() == MyEventType)  
  30.     {  
  31.         qDebug()<<"MyEventType is coming!";  
  32.         //return true;  
  33.         /*這裏不能return true,由於重寫notify就是在事件被向下傳遞以前截住它, 
  34.         隨便搞它,搞完了還得給QCoreApplication::notify向下傳遞,除非在mySender.notify 
  35.         實現了事件向下傳遞的那一套。直接返回的話myArmy就收不到這個事件,由於執行完這個 
  36.         mySender.notify的return true後,事件傳遞被人爲的在半截終止了 
  37.         (見Qt事件處理的五個層次http://blog.csdn.net/michealtx/article/details/6865891 ) 
  38.         ,下面的myArmy的安裝的過濾器和它本身的event都不會收到這個事件,更甭提最後幹活 
  39.         的myEventHandler了。因此在主函數中執行完mySender.sendEvent把myEvent 
  40.         交給mySender.notify這個敗家子兒後,就執行mySender.exec進入其它事件的循環了。這就是 
  41.         問題http://topic.csdn.net/u/20111012/19/78036d16-c163-40f9-a05c-3b7d6f4e9043.html 
  42.         出現的緣由。感謝1+1=2大牛!很是感謝! 
  43.         */  
  44.     }  
  45.     return QCoreApplication::notify(receiver,event);  
  46. }  
  47.   
  48. //軍隊  
  49. class MyArmy: public QObject  
  50. {  
  51. public:  
  52.     void MyEventHandler(QEvent *event);  
  53.     bool event(QEvent *event);  
  54. };  
  55.   
  56. void MyArmy::MyEventHandler(QEvent *event)  
  57. {  
  58.     qDebug()<<"The event is being handled!";  
  59.     event->accept();  
  60. }  
  61.   
  62. bool MyArmy::event(QEvent *event)  
  63. {  
  64.     if(event->type() == MyEventType)  
  65.     {  
  66.         qDebug()<<"event() is dispathing MyEvent";  
  67.         MyEventHandler(event);//調用事件處理函數  
  68.         if((MyEvent*)event->isAccepted())  
  69.         {  
  70.             qDebug()<<"The event has been handled!";  
  71.             return true;  
  72.         }  
  73.     }  
  74.     return QObject::event(event);  
  75. }  
  76.   
  77. //監控者  
  78. class MyWatcher: public QObject  
  79. {  
  80. public:  
  81.     bool eventFilter(QObject *watched, QEvent *event);  
  82. };  
  83.   
  84. bool MyWatcher::eventFilter(QObject *watched, QEvent *event)  
  85. {  
  86.     if(event->type() == MyEventType)  
  87.     {  
  88.         qDebug()<<"I don't wanna filter MyEventType";  
  89.         return false;  
  90.     }  
  91.     return QObject::eventFilter(watched,event);  
  92. }  
  93.   
  94.   
  95. int main(int argc, char *argv[])  
  96. {  
  97.     //QCoreApplication a(argc, argv);  
  98.     MySender mySender(argc,argv);  
  99.   
  100.     MyArmy myArmy;  
  101.     MyWatcher myWatcher;  
  102.     myArmy.installEventFilter(&myWatcher);//安裝事件過濾器  
  103.   
  104.     MyEvent myEvent(MyEventType);  
  105.     mySender.sendEvent(&myArmy,&myEvent);  
  106.     return mySender.exec();  
  107. }  



運行結果:

 

相關文章
相關標籤/搜索