QT文档中这样解释:
sendEvent(QObject* receiver,QEvent* event)
使用notify()函数直接给receiver发送事件。
postEvent(QObject* receiver, QEvent* event)
向事件队列中添加receiver和event。
简单说,sendEvent使用的是同步处理事件,postEvent使用的异步处理事件
sendEvent代码分析
- inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
- { if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }
直接调用notifyInternal接口,注意中间设置自发消息标志位为false,同时还需要判断self是有有效(QCoreApplication是否启动)
- bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
- {
- // Make it possible for Qt Jambi and QSA to hook into events even
- // though QApplication is subclassed...
- bool result = false;
- void *cbdata[] = { receiver, event, &result };
- if (QInternal::activateCallbacks(QInternal::EventNotifyCallback, cbdata)) {
- return result;
- }
- // Qt enforces the rule that events can only be sent to objects in
- // the current thread, so receiver->d_func()->threadData is
- // equivalent to QThreadData::current(), just without the function
- // call overhead.
- QObjectPrivate *d = receiver->d_func();
- QThreadData *threadData = d->threadData;
- ++threadData->loopLevel;
- bool returnValue = notify(receiver, event);
- --threadData->loopLevel;
- return returnValue;
- }
- 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;
- }
- 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);
- }
在这里可以看到事件是如何处理的:
- 先送入Application的事件过滤器,看看是否在事件过滤器中处理
- 再查看receiver是否有此事件的过滤器
- 最后,将事件送入receiver的event接口。
从整个过程来看,可以认为sendEvent直接调用了receiver的event接口。因此,可以认为处理方式为同步处理方式。
PostEvent分析
- void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
- {
- postEvent(receiver, event, Qt::NormalEventPriority);
- }
- void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
- {
- ...
- QThreadData * volatile * pdata = &receiver->d_func()->threadData; //得到线程信息
- QThreadData *data = *pdata;
- if (!data) {
- // posting during destruction? just delete the event to prevent a leak
- delete event;
- return;
- }
- // lock the post event mutex
- data->postEventList.mutex.lock();
- // if object has moved to another thread, follow it
- while (data != *pdata) { <span style="font-family: Arial, Helvetica, sans-serif;">//在这里判断receiver线程信息是否发生变化。(有可能是另外一个线程调用用receiver->moveToThread)</span>
- data->postEventList.mutex.unlock();
- data = *pdata;
- if (!data) {
- // posting during destruction? just delete the event to prevent a leak
- delete event;
- return;
- }
- data->postEventList.mutex.lock();
- }
- //这里postEventList还是被锁着的。
- // if this is one of the compressible events, do compression
- if (receiver->d_func()->postedEvents
- && self && self->compressEvent(event, receiver, &data->postEventList)) {
- data->postEventList.mutex.unlock();//这个事件有可能被压缩(实际上是发现队列中有这个事件还没有被处理,且这个事件是可以被压缩的,例如paintevent)
- return;
- }
- event->posted = true;
- ++receiver->d_func()->postedEvents;
- if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
- // remember the current running eventloop for DeferredDelete
- // events posted in the receiver's thread
- event->d = reinterpret_cast<QEventPrivate *>(quintptr(data->loopLevel)); //receiver即将被析构?
- }
- //将事件添加到postEventList中,注意这里的优先级第一个最高,最后一个优先级最低
- if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) {
- // optimization: we can simply append if the last event in
- // the queue has higher or equal priority
- data->postEventList.append(QPostEvent(receiver, event, priority));
- } else {
- // insert event in descending priority order, using upper
- // bound for a given priority (to ensure proper ordering
- // of events with the same priority)
- QPostEventList::iterator begin = data->postEventList.begin()
- + data->postEventList.insertionOffset,
- end = data->postEventList.end();
- QPostEventList::iterator at = qUpperBound(begin, end, priority);
- data->postEventList.insert(at, QPostEvent(receiver, event, priority));
- }
- data->canWait = false;
- data->postEventList.mutex.unlock();//在这里解除锁
- //receiver所在的线程调用eventDispatcher处理postEventList
- if (data->eventDispatcher)
- data->eventDispatcher->wakeUp();
- }