1. 程式人生 > >Qt事件處理

Qt事件處理

Qt事件處理

Qt事件處理的五個層次

Qt 應用程式 事件處理 的五個層次,同時也是時間流程如下圖所示:

說明如下:

  1. sendEvent()會把event直接傳送給QCoreApplication的notify(),postEvent()把event追加到事件佇列中最終也要呼叫notify()。
  2. notify()把事件分發給引數中的receiver,如果receiver安裝了eventFilter,那麼event會發給定義這個事件過濾器的監控者,如果這個event沒有被過濾,那麼這個event會被傳給receiver的event()函式。
  3. event()函式再把這個event傳給與其相應的事件處理函式(諸如keyPressEvent()之類的函式)。這些事件處理函式這才是真正響應event的函式,它們才是真正幹活的,到這裡算是處理完了。
  4. 這個過程中,許可權是由大到小的,不算sendEvent()和postEvent和事件迴圈,notify具有最大控制權,因為它最先見到event,我們可以重寫notify()開始的這個處理鏈上的函式來響應event,從而進行相應的操作。
  5. 整個流程中,只有postEvent()和最後的事件處理函式是void型別,其它函式都是bool型。

QT 自定義事件

Qt自定義事件的實現也是按照五個層次的原理實現的

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

要注意:

當使用sendEvent時,你的事件要在棧上建立,sendEvent會直接呼叫notify把事件傳遞給士兵,不走事件佇列;而用postEvent時,你的事件要在堆上建立,即要用new來建立,postEvent會把你的事件追加進事件佇列