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会把你的事件追加进事件队列

 

猜你喜欢

转载自www.cnblogs.com/Yu-900914/p/10036116.html
今日推荐