Qt事件处理机制
来源:互联网 发布:郑州丰泽教育编程 编辑:程序博客网 时间:2024/05/02 04:20
Qt事件处理机制
一、创建事件QEvent
Qt事件的来源:
-1.系统产生的:通常是window system 把从系统得到的消息,比如鼠标按键等放入系统的消息队列中,Qt事件循环的时候读取这些事件,转化为QEvent.
-2.Qt应用程序自身产生的。
自定义事件
在上述Qt事件来源的第二种方式中,又可分为两种:
-1.Qt预定义的事件
-2.用户自定义事件
用户自定义事件步骤
-1).注册事件ID:
static int QEvent::registerEventType( int hint = -1 ) ;函数返回一个可用的用户事件ID
-2).从QEvent派生出自定义事件,此步骤在调用QEvent构造函数时会使用到第一步注册的ID
二、发送事件
postEvent()
static void QCoreApplication::postEvent( QObject receiver ,QEvent event ,
int priority )
此函数会把事件发送到一个事件队列中
sendEvent()
static bool QCoreApplication::sendEvent( QObject * receiver , QEvent * event)
此函数不会把事件发送到事件队列中
三、事件分发
对于以postEvent()方式发送的事件,会被放入事件队列,然后通过事件循环机制每次从队列中取出一个事件,取出的事件会交给notify()函数,这个函数负责事件的分发。对于以sendEvent()方式发送的事件,不会经历事件循环这个过程,而是直接交由notify()函数进行分发。下面我们来分析notify()实现细节,以下代码是从Qt源码中摘抄的。
bool QCoreApplication::notify(QObject *receiver, QEvent *event){ Q_D(QCoreApplication); // no events are delivered after ~QCoreApplication() has started if (QCoreApplicationPrivate::is_app_closing) return true; if (receiver == 0) { // serious error qWarning("QCoreApplication::notify: Unexpected null receiver"); return true; }#ifndef QT_NO_DEBUG d->checkReceiverThread(receiver);#endif return receiver->isWidgetType() ? false : d->notify_helper(receiver, event); }
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event){ // send to all application event filters if (sendThroughApplicationEventFilters(receiver, event)) return true; // send to all receiver event filters if (sendThroughObjectEventFilters(receiver, event)) return true; // deliver the event return receiver->event(event);}
bool QObject::event(QEvent *e){ switch (e->type()) { case QEvent::Timer: timerEvent((QTimerEvent*)e); break;#ifdef QT3_SUPPORT case QEvent::ChildInsertedRequest: d_func()->sendPendingChildInsertedEvents(); break;#endif case QEvent::ChildAdded: case QEvent::ChildPolished:#ifdef QT3_SUPPORT case QEvent::ChildInserted:#endif case QEvent::ChildRemoved: childEvent((QChildEvent*)e); break; case QEvent::DeferredDelete: qDeleteInEventHandler(this); break; case QEvent::MetaCall: {#ifdef QT_JAMBI_BUILD d_func()->inEventHandler = false;#endif QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); QObjectPrivate::Sender currentSender; currentSender.sender = const_cast<QObject*>(mce->sender()); currentSender.signal = mce->signalId(); currentSender.ref = 1; QObjectPrivate::Sender * const previousSender = QObjectPrivate::setCurrentSender(this, ¤tSender);#if defined(QT_NO_EXCEPTIONS) mce->placeMetaCall(this);#else QT_TRY { mce->placeMetaCall(this); } QT_CATCH(...) { QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender); QT_RETHROW; }#endif QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender); break; } case QEvent::ThreadChange: { Q_D(QObject); QThreadData *threadData = d->threadData; QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher; if (eventDispatcher) { QList<QPair<int, int> > timers = eventDispatcher-> registeredTimers(this); if (!timers.isEmpty()) { // set inThreadChangeEvent to true to tell the dispatcher not to release out timer ids // back to the pool (since the timer ids are moving to a new thread). d->inThreadChangeEvent = true; eventDispatcher->unregisterTimers(this); d->inThreadChangeEvent = false; QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection, Q_ARG(void*, (new QList<QPair<int, int> >(timers)))); } } break; } default: if (e->type() >= QEvent::User) { customEvent(e); break; } return false; } return true;}
以上的代码实现细节不需要逐一去理解,只需要搞清楚各个函数的调用关系。首先,notify()函数在最后调用了notify_helper()函数。notify_helper()函数又调用了
return receiver->event(event);event()函数我们可以仔细研究下,其实event()就是根据QEvent的类型对事件进行分派,实现相应事件调用相应的事件处理器。
四、事件处理器
在上面的event()函数中,形如 timerEvent((QTimerEvent*)e);的函数就是事件处理器。在qt中,对Qt事件的使用,最终都是归于对事件处理器的重写。
五、事件处理机制流程图
到目前为止,我们已经可以运用Qt提供的事件完成想要实现的功能。使用事件的最基本也是最多的思路是:重载事件处理函数,把要实现的功能以代码的形式写在事件处理函数中。
这种方法可以应付Qt中大多数情况下的应用需求,但是在某些情况下直接重载事件处理器显得过于复杂。对此,Qt提供了事件过滤器。
六、事件过滤器
事件过滤器可以在一个对象处理事件之前调用。
应用事件过滤器很简单,其中只涉及两个函数:installEventFilter()和eventFilter()
如:
-1.A->installEventFilter(B);
-2.重新实现B所对应的类的eventFilter()函数
这就是实现B监视A所需要的全部代码。
原理
对于所有的QObject对象,都有一个QObjectList类型的对象eventFilters,当对一个对象调用installEventFilter时,如:A->installEventFilter(B),此函数会把指向B的指针存入A的eventfilters中。当一个事件发生时,在执行event()之前,Qt会首先检查对象的eventfilters是否为空,若不为空,则对其中指针所指向对象调用eventFilter()函数。函数执行完后,再根据返回值来确定要不要再次执行此事件。若eventFilter()函数返回true,则不会再次执行此事件。否则会继续执行此事件。
下面是Qt源码中installEventFilter()函数的实现:
void QObject::installEventFilter(QObject *obj){ Q_D(QObject); if (!obj) return; if (d->threadData != obj->d_func()->threadData) { qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread."); return; } // clean up unused items in the list d->eventFilters.removeAll((QObject*)0); d->eventFilters.removeAll(obj); d->eventFilters.prepend(obj);}
eventFilter()的优先级
待续。。。。。
- Qt事件处理机制
- Qt事件处理机制
- Qt事件处理机制
- Qt事件处理机制
- qt事件处理机制
- Qt事件驱动处理机制
- Qt事件处理机制详解
- Qt中的事件处理机制
- java .net MFC QT事件处理机制
- Qt的事件处理机制分析
- Qt的事件处理机制分析
- Qt的事件处理机制分析
- 浅议Qt的事件处理机制 二
- 浅议Qt的事件处理机制 一
- Qt 事件处理机制 (上篇)
- qt按键事件处理机制分析
- 浅议Qt的事件处理机制 一
- 浅议Qt的事件处理机制 二
- 把excel自动导入数据库 根据excel内容自动创建数据库表
- 树莓派重新启动和复位的方法
- Python 爬虫中遇到的反爬虫问题
- 【poj1008】玛雅历
- java sax解析xml
- Qt事件处理机制
- java的volatile机制(前篇)
- 迷茫的孩子
- J2SE-选择排序法初识
- 去掉标题栏的JFrame如何实现拖动
- Linux下源码安装mysql及mysql的简单用法
- Java并发编程:volatile关键字解析
- Android NDK开发 在eclipse中添加C方法代码提示
- 匿名对象的深入分析