QT文档中这样解释:
sendEvent(QObject* receiver,QEvent* event)
使用notify()函数直接给receiver发送事件。
postEvent(QObject* receiver, QEvent* event)
向事件队列中添加receiver和event。
简单说,sendEvent使用的是同步处理事件,postEvent使用的异步处理事件
inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
{ if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }
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;
}
删除了一些不重要的代码,notifyInternal的主要作用是activateCallbacks,直接看notify
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);
}
这个接口在QT文档上有注释。注意其中当receiver为控件时,不进行处理。
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);
}
从整个过程来看,可以认为sendEvent直接调用了receiver的event接口。因此,可以认为处理方式为同步处理方式。
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) { //在这里判断receiver线程信息是否发生变化。(有可能是另外一个线程调用用receiver->moveToThread)
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(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();
}
从上面可以看出,postEvent实际上是将事件添加到receiver所在线程中的一个队列中,至于这个队列所在的线程什么时候处理这个事件,postEvent是无法控制的