📄 qcoreapplication.cpp
字号:
The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. It is \e {not safe} to modify or delete the event after it has been posted. When control returns to the main event loop, all events that are stored in the queue will be sent using the notify() function. Events are processed in the order posted. For more control over the processing order, use the postEvent() overload below, which takes a priority argument. This function posts all event with a Qt::NormalEventPriority. \threadsafe \sa sendEvent(), notify(), sendPostedEvents()*/void QCoreApplication::postEvent(QObject *receiver, QEvent *event){ postEvent(receiver, event, Qt::NormalEventPriority);}/*! \overload \since 4.3 Adds the event \a event, with the object \a receiver as the receiver of the event, to an event queue and returns immediately. The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. It is \e {not safe} to modify or delete the event after it has been posted. When control returns to the main event loop, all events that are stored in the queue will be sent using the notify() function. Events are sorted in descending \a priority order, i.e. events with a high \a priority are queued before events with a lower \a priority. The \a priority can be any integer value, i.e. between INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more details. Events with equal \a priority will be processed in the order posted. \threadsafe \sa sendEvent(), notify(), sendPostedEvents(), Qt::EventPriority*/void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority){ if (receiver == 0) { qWarning("QCoreApplication::postEvent: Unexpected null receiver"); delete event; return; } QReadLocker locker(QObjectPrivate::readWriteLock()); if (!QObjectPrivate::isValidObject(receiver)) { qWarning("QCoreApplication::postEvent: Receiver is not a valid QObject"); delete event; return; } QThreadData *data = receiver->d_func()->threadData; if (!data) { // posting during destruction? just delete the event to prevent a leak delete event; return; } { QMutexLocker locker(&data->postEventList.mutex); // if this is one of the compressible events, do compression if (receiver->d_func()->postedEvents && self && self->compressEvent(event, receiver, &data->postEventList)) { return; } event->posted = true; ++receiver->d_func()->postedEvents; ++data->postEventList.numPostedEvents; if (event->type() == QEvent::DeferredDelete) { if (!data->eventLoops.isEmpty()) { // remember the current running eventloop for (int i = data->eventLoops.size() - 1; i >= 0; --i) { QEventLoop *eventLoop = data->eventLoops.at(i); if (eventLoop->isRunning()) { event->d = reinterpret_cast<QEventPrivate *>(eventLoop); break; } } } } 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.offset, end = data->postEventList.end(); QPostEventList::iterator at = qUpperBound(begin, end, priority); data->postEventList.insert(at, QPostEvent(receiver, event, priority)); } data->canWait = false; } if (data->eventDispatcher) data->eventDispatcher->wakeUp();}/*! \internal Returns true if \a event was compressed away (possibly deleted) and should not be added to the list.*/bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents){#ifdef Q_WS_WIN Q_ASSERT(event); Q_ASSERT(receiver); Q_ASSERT(postedEvents); // compress posted timers to this object. if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) { int timerId = ((QTimerEvent *) event)->timerId(); for (int i=0; i<postedEvents->size(); ++i) { const QPostEvent &e = postedEvents->at(i); if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer && ((QTimerEvent *) e.event)->timerId() == timerId) { delete event; return true; } } } else#endif if (event->type() == QEvent::DeferredDelete && receiver->d_func()->postedEvents > 0) { for (int i = 0; i < postedEvents->size(); ++i) { const QPostEvent &cur = postedEvents->at(i); if (cur.receiver != receiver || cur.event == 0 || cur.event->type() != event->type()) continue; // found a DeferredDelete for this receiver delete event; return true; } } return false;}/*! \fn void QCoreApplication::sendPostedEvents() \overload Dispatches all posted events, i.e. empties the event queue.*//*! Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent() and which are for the object \a receiver and have the event type \a event_type. Note that events from the window system are \e not dispatched by this function, but by processEvents(). If \a receiver is null, the events of \a event_type are sent for all objects. If \a event_type is 0, all the events are sent for \a receiver. \sa flush(), postEvent()*/void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type){ QThreadData *data = QThreadData::current(); QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);}void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type, QThreadData *data){ bool doDeferredDeletion = (event_type == QEvent::DeferredDelete); if (event_type == -1) { // we were called by the event dispatcher. doDeferredDeletion = true; event_type = 0; } if (receiver && receiver->d_func()->threadData != data) { qWarning("QCoreApplication::sendPostedEvents: Cannot send " "posted events for objects in another thread"); return; } ++data->postEventList.recursion;#ifdef QT3_SUPPORT if (event_type == QEvent::ChildInserted) { if (receiver) { // optimize sendPostedEvents(w, QEvent::ChildInserted) calls away receiver->d_func()->sendPendingChildInsertedEvents(); --data->postEventList.recursion; return; } // ChildInserted events are sent in response to *Request event_type = QEvent::ChildInsertedRequest; }#endif QMutexLocker locker(&data->postEventList.mutex); // by default, we assume that the event dispatcher can go to sleep after // processing all events. if any new events are posted while we send // events, canWait will be set to false. data->canWait = (data->postEventList.size() == 0); if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) { --data->postEventList.recursion; return; } data->canWait = true; // okay. here is the tricky loop. be careful about optimizing // this, it looks the way it does for good reasons. int i = 0; const int s = data->postEventList.size(); const int savedOffset = data->postEventList.offset; data->postEventList.offset = s; while (i < data->postEventList.size()) { // avoid live-lock if (i >= s) break; const QPostEvent &pe = data->postEventList.at(i); ++i; if (!pe.event) continue; if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) { data->canWait = false; continue; } if (pe.event->type() == QEvent::DeferredDelete) { QEventLoop *savedEventLoop = reinterpret_cast<QEventLoop *>(pe.event->d); QEventLoop *currentEventLoop = data->eventLoops.isEmpty() ? 0 : data->eventLoops.top(); bool savedEventLoopIsRunning = data->eventLoops.contains(savedEventLoop); // DeferredDelete events are only sent when we are explicitly // asked to (s.a. QEventLoop::DeferredDeletion), and then only if // there is no current event loop, or if the current event loop is // equal to the loop in which deleteLater() was called. if (!doDeferredDeletion || (currentEventLoop && savedEventLoop && savedEventLoop != currentEventLoop && savedEventLoopIsRunning)) { // cannot send deferred delete if (!event_type && !receiver) { // don't lose the event data->postEventList.append(pe); const_cast<QPostEvent &>(pe).event = 0; } continue; } } // first, we diddle the event so that we can deliver // it, and that no one will try to touch it later. pe.event->posted = false; QEvent * e = pe.event; QObject * r = pe.receiver; --r->d_func()->postedEvents; --data->postEventList.numPostedEvents; Q_ASSERT(r->d_func()->postedEvents >= 0); // next, update the data structure so that we're ready // for the next event. const_cast<QPostEvent &>(pe).event = 0; locker.unlock(); // after all that work, it's time to deliver the event.#ifdef QT_NO_EXCEPTIONS QCoreApplication::sendEvent(r, e);#else try { QCoreApplication::sendEvent(r, e); } catch (...) { delete e; locker.relock(); // since we were interrupted, we need another pass to make sure we clean everything up data->canWait = false; // uglehack: copied from below data->postEventList.offset = savedOffset; --data->postEventList.recursion; if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) data->eventDispatcher->wakeUp(); throw; // rethrow }#endif delete e; locker.relock(); // careful when adding anything below this point - the // sendEvent() call might invalidate any invariants this // function depends on. } data->postEventList.offset = savedOffset; --data->postEventList.recursion; if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) data->eventDispatcher->wakeUp(); // clear the global list, i.e. remove everything that was // delivered. if (!data->postEventList.recursion && !event_type && !receiver) { const QPostEventList::iterator it = data->postEventList.begin(); data->postEventList.erase(it, it + i); }}/*! Removes all events posted using postEvent() for \a receiver. The events are \e not dispatched, instead they are removed from the queue. You should never need to call this function. If you do call it, be aware that killing events may cause \a receiver to break one or more invariants. \threadsafe*/void QCoreApplication::removePostedEvents(QObject *receiver){ removePostedEvents(receiver, 0);}/*! \overload \since 4.3 Removes all events of the given \a eventType that were posted using postEvent() for \a receiver. The events are \e not dispatched, instead they are removed from the queue. You should never need to call this function. If you do call it, be aware that killing events may cause \a receiver to break one or more invariants. If \a receiver is null, the events of \a eventType are removed for all objects. If \a eventType is 0, all the events are removed for \a receiver. \threadsafe*/void QCoreApplication::removePostedEvents(QObject *receiver, int eventType){#ifdef QT3_SUPPORT if (eventType == QEvent::ChildInserted) eventType = QEvent::ChildInsertedRequest;#endif QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current(); QMutexLocker locker(&data->postEventList.mutex); // the QObject destructor calls this function directly. this can // happen while the event loop is in the middle of posting events, // and when we get here, we may not have any more posted events // for this object. if (receiver && !receiver->d_func()->postedEvents) return; int n = data->postEventList.size(); int j = 0; for (int i = 0; i < n; ++i) { const QPostEvent &pe = data->postEventList.at(i); if ((!receiver || pe.receiver == receiver) && (pe.event && (eventType == 0 || pe.event->type() == eventType))) { --pe.receiver->d_func()->postedEvents;#ifdef QT3_SUPPORT if (pe.event->type() == QEvent::ChildInsertedRequest) pe.receiver->d_func()->removePendingChildInsertedEvents(0);#endif pe.event->posted = false; delete pe.event; const_cast<QPostEvent &>(pe).event = 0; } else if (!data->postEventList.recursion) { if (i != j) data->postEventList.swap(i, j); ++j; } }#ifdef QT_DEBUG if (receiver && eventType == 0) { Q_ASSERT(!receiver->d_func()->postedEvents); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -