QT 之 sendEvent & PostEvent
来源:互联网 发布:温斯洛体测数据 编辑:程序博客网 时间:2024/05/16 07:03
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;}删除了一些不重要的代码,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);}
在这里可以看到事件是如何处理的:
- 先送入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();}从上面可以看出,postEvent实际上是将事件添加到receiver所在线程中的一个队列中,至于这个队列所在的线程什么时候处理这个事件,postEvent是无法控制的
0 0
- QT 之 sendEvent & PostEvent
- QT sendEvent()和postEvent()
- QT sendEvent()和postEvent()
- QEvent postEvent/sendEvent
- QEvent postEvent/sendEvent
- QEvent postEvent/sendEvent
- QEvent postEvent/sendEvent
- Qt postEvent
- CTK 事件管理机制(sendEvent()/postEvent())
- [Qt] postevent emit
- qt2.2 多线程发送消息 QThread::postEvent postEvent qApp->postEvent QApplication qt 消息
- [Qt] postevent emit ----event与signal
- qt信号与槽代替postevent
- sendevent
- sendevent
- android测试之getevent/sendevent
- android测试之getevent/sendevent
- android测试之getevent/sendevent
- 服务器备份工具
- TCP的拥塞控制
- Android版本和API Level的对应关系
- 汪金梓:5月28日黄金、白银、原油走势分析
- 删除一个数组中指定位置的元素
- QT 之 sendEvent & PostEvent
- 关于自定义Dialog 中match_parent 属性 失效的问题
- Jboss EAP6 新特性
- nginx基本数据结构ngx_module_t,ngx_module_s
- git问题解决办法收录
- SpringMVC @RequestBody 自动转json Http415错误
- Gson
- 如何在ArrayList<Integer>中添加String类型数据
- CleanMyMac3时刻保证Mac清洁和健康好帮手