作者:kakaka2011
转自:http://blog.youkuaiyun.com/love_gaohz/article/details/10510675
在Qt中我们会遇到两种事件一种是Qt中的系统时间了,另外一种就是Qt自定义事件。
Qt 的自定义事件主要的实现:
Qt 的事件处理,实际上是有五个层次:重定义事件处理函数,重定义event()函数,为单个组件安装事件过滤器,为QApplication安装事件过滤器,重定义QCoreApplication的notify()函数。这几个层次的控制权是逐层增大的。
重要函数:
|
该函数会将 event 发送给 receiver,也就是调用 receiver->event(event),其返回值就是来自 receiver 的事件处理器。
QCoreApplication::sendEvent()或者QCoreApplication:;postEvent()的区别?
①static bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event);
直接将 event 事件发送给 receiver 接受者,使用的是 QCoreApplication::notify() 函数。函数返回值就是事件处理函数的返回值。在事件被发送的时候,event 对象并不会被销毁。通常我们会在栈上创建 event 对象,例如:
- QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
- QApplication::sendEvent(mainWindow, &event);
② static void QCoreApplication::postEvent(QObject *receiver, QEvent *event);
将 event 事件及其接受者 receiver 一同追加到事件队列中,函数立即返回。
因为 post 事件队列会持有事件对象,并且在其 post 的时候将其 delete 掉,因此,我们必须在堆上创建event 对象。当对象被发送之后,再试图访问 event 对象就会出现问题(因为 post 之后,event 对象就会被 delete)。
当控制权返回到主线程循环是,保存在事件队列中的所有事件都通过 notify() 函数发送出去。
事件会根据 post 的顺序进行处理。如果你想要改变事件的处理顺序,可以考虑为其指定一个优先级。默认的优先级是 Qt::NormalEventPriority。
这个函数是线程安全的。
简单的说就是:sendEvent()会把event直接使用QCoreApplication的notify()发送给receiver,postEvent()把event追加到事件队列中最终也要调用notify(),notify()把事件分发给参数中的receiver,如果receiver安装了eventFilter,那么event会发给定义这个事件过滤器的监控者,如果这个event没有被过滤,那么这个event会被传给receiver的event()函数,event()函数再把这个event传给与其相应的事件处理函数(诸如keyPressEvent()之类的函数)。这些事件处理函数这才是真正响应event的函数,它们才是真正干活的,到这里算是处理完了。
引用别人的代码实现:
- #include <qcoreapplication>
- #include <qevent>
- #include <qobject>
- #include <qdebug>
- static const QEvent::Type MyEventType = (QEvent::Type)QEvent::registerEventType(QEvent::User+100);
- //长官
- class MyEvent: public QEvent
- {
- public:
- MyEvent(Type MyEventType):QEvent(MyEventType){}
- };
- //信使
- class MySender: public QCoreApplication
- {
- public:
- MySender(int argc,char *argv[]):QCoreApplication(argc,argv){}
- public:
- bool notify(QObject *receiver, QEvent *event);
- };
- bool MySender::notify(QObject *receiver, QEvent *event)
- {
- if(event->type() == MyEventType)
- {
- qDebug()<<"MyEventType is coming!";
- //return true;
- /*这里不能return true,因为重写notify就是在事件被向下传递之前截住它,
- 随便搞它,搞完了还得给QCoreApplication::notify向下传递,除非在mySender.notify
- 实现了事件向下传递的那一套。直接返回的话myArmy就收不到这个事件,因为执行完这个
- mySender.notify的return true后,事件传递被人为的在半截终止了
- (见Qt事件处理的五个层次http://blog.youkuaiyun.com/michealtx/article/details/6865891 )
- ,下面的myArmy的安装的过滤器和它自己的event都不会收到这个事件,更甭提最后干活
- 的myEventHandler了。所以在主函数中执行完mySender.sendEvent把myEvent
- 交给mySender.notify这个败家子儿后,就执行mySender.exec进入其它事件的循环了。这就是
- 问题http://topic.youkuaiyun.com/u/20111012/19/78036d16-c163-40f9-a05c-3b7d6f4e9043.html
- 出现的原因。感谢1+1=2大牛!非常感谢!
- */
- }
- return QCoreApplication::notify(receiver,event);
- }
- //军队
- class MyArmy: public QObject
- {
- public:
- void MyEventHandler(QEvent *event);
- bool event(QEvent *event);
- };
- void MyArmy::MyEventHandler(QEvent *event)
- {
- qDebug()<<"The event is being handled!";
- event->accept();
- }
- bool MyArmy::event(QEvent *event)
- {
- if(event->type() == MyEventType)
- {
- qDebug()<<"event() is dispathing MyEvent";
- MyEventHandler(event);//调用事件处理函数
- if((MyEvent*)event->isAccepted())
- {
- qDebug()<<"The event has been handled!";
- return true;
- }
- }
- return QObject::event(event);
- }
- //监控者
- class MyWatcher: public QObject
- {
- public:
- bool eventFilter(QObject *watched, QEvent *event);
- };
- bool MyWatcher::eventFilter(QObject *watched, QEvent *event)
- {
- if(event->type() == MyEventType)
- {
- qDebug()<<"I don't wanna filter MyEventType";
- return false;
- }
- return QObject::eventFilter(watched,event);
- }
- int main(int argc, char *argv[])
- {
- //QCoreApplication a(argc, argv);
- MySender mySender(argc,argv);
- MyArmy myArmy;
- MyWatcher myWatcher;
- myArmy.installEventFilter(&myWatcher);//安装事件过滤器
- MyEvent myEvent(MyEventType);
- mySender.sendEvent(&myArmy,&myEvent);
- return mySender.exec();
- }
- </qdebug></qobject></qevent></qcoreapplication>
解释:
大体的实现是按照
①自定义QEvent::Type 用到QEvent::registerEventType();这个函数。
②重写QCoreApplication::notify(QObject*receiver,QEvent*event)它主要负责把事件发给接受者。
③实现QObject 的eventFilter函数,进行事件的过滤。不过滤事件return false;
④重定义event()函数,重定义事件处理函数,处理函数中可以调用event->accept();event->ignore()正如它们的名字一样,前者用来告诉 Qt,这个类的事件处理函数想要这个事件;后者则告诉 Qt,这个类的事件处理函数不想要这个事件。