基本结构
QCoreApplication在exec时,会使用QEventLoop
QEventLoop在处理事件时,会调用事件分发器QAbstractEventDispatcher ,针对不同的平台,事件分发器有不同的实现
QEventDispatcherUNIX
以QEventDispatcherUNIX的分发为例,其时序为
在处理事件前,会经过应用和事件接收者的过滤处理
// send to all application event filters (only does anything in the main thread)
if (QCoreApplication::self
&& receiver->d_func()->threadData->thread.loadAcquire() == mainThread()
&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
filtered = true;
return filtered;
}
// send to all receiver event filters
if (sendThroughObjectEventFilters(receiver, event)) {
filtered = true;
return filtered;
}
事件过滤器是定义在QObjectPrivate中结构体ExtraData中
事件过滤器eventFilter和事件处理event方法是定义在QObject中
QEventDispatcherWin32
DispatchMessage:是将消息分发到窗口的处理函数
QEvent类层次
QEvent:在qcoreevent.h文件中定义
事件过滤器
包含安装,卸载,过滤
// QAbstractEventDispatcher
void installNativeEventFilter(QAbstractNativeEventFilter *filterObj);
void removeNativeEventFilter(QAbstractNativeEventFilter *filterObj);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result);
#else
bool filterNativeEvent(const QByteArray &eventType, void *message, long *result);
#endif
class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QAbstractEventDispatcher)
public:
inline QAbstractEventDispatcherPrivate()
{ }
QList<QAbstractNativeEventFilter *> eventFilters;
static int allocateTimerId();
static void releaseTimerId(int id);
};
void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
{
Q_D(QAbstractEventDispatcher);
// clean up unused items in the list
d->eventFilters.removeAll(0);
d->eventFilters.removeAll(filterObj);
d->eventFilters.prepend(filterObj);
}
void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilter *filter)
{
Q_D(QAbstractEventDispatcher);
for (int i = 0; i < d->eventFilters.count(); ++i) {
if (d->eventFilters.at(i) == filter) {
d->eventFilters[i] = 0;
break;
}
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
Q_D(QAbstractEventDispatcher);
if (!d->eventFilters.isEmpty()) {
// Raise the loopLevel so that deleteLater() calls in or triggered
// by event_filter() will be processed from the main event loop.
QScopedScopeLevelCounter scopeLevelCounter(d->threadData);
for (int i = 0; i < d->eventFilters.size(); ++i) {
QAbstractNativeEventFilter *filter = d->eventFilters.at(i);
if (!filter)
continue;
if (filter->nativeEventFilter(eventType, message, result))
return true;
}
}
return false;
}
//QObject
void installEventFilter(QObject *filterObj);
void removeEventFilter(QObject *obj);
virtual bool eventFilter(QObject *watched, QEvent *event);
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;
}
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
// clean up unused items in the list
d->extraData->eventFilters.removeAll((QObject*)0);
d->extraData->eventFilters.removeAll(obj);
d->extraData->eventFilters.prepend(obj);
}
void QObject::removeEventFilter(QObject *obj)
{
Q_D(QObject);
if (d->extraData) {
for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {
if (d->extraData->eventFilters.at(i) == obj)
d->extraData->eventFilters[i] = 0;
}
}
}
bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
{
return false;
}
发送事件
分为同步和异步
同步是sendEvent,异步是postEvent,构造QPostEvent添加到队列data->postEventList中
bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
{
Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
if (event)
event->spont = false;
return notifyInternal2(receiver, event);
}
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
Q_TRACE_SCOPE(QCoreApplication_postEvent, receiver, event, event->type());
if (receiver == 0) {
qWarning("QCoreApplication::postEvent: Unexpected null receiver");
delete event;
return;
}
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) {
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();
}
QMutexUnlocker 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)) {
Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
return;
}
if (event->type() == QEvent::DeferredDelete)
receiver->d_ptr->deleteLaterCalled = true;
if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
// remember the current running eventloop for DeferredDelete
// events posted in the receiver's thread.
// Events sent by non-Qt event handlers (such as glib) may not
// have the scopeLevel set correctly. The scope level makes sure that
// code like this:
// foo->deleteLater();
// qApp->processEvents(); // without passing QEvent::DeferredDelete
// will not cause "foo" to be deleted before returning to the event loop.
// If the scope level is 0 while loopLevel != 0, we are called from a
// non-conformant code path, and our best guess is that the scope level
// should be 1. (Loop level 0 is special: it means that no event loops
// are running.)
int loopLevel = data->loopLevel;
int scopeLevel = data->scopeLevel;
if (scopeLevel == 0 && loopLevel != 0)
scopeLevel = 1;
static_cast<QDeferredDeleteEvent *>(event)->level = loopLevel + scopeLevel;
}
// delete the event on exceptions to protect against memory leaks till the event is
// properly owned in the postEventList
QScopedPointer<QEvent> eventDeleter(event);
Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
data->postEventList.addEvent(QPostEvent(receiver, event, priority));
eventDeleter.take();
event->posted = true;
++receiver->d_func()->postedEvents;
data->canWait = false;
locker.unlock();
QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
if (dispatcher)
dispatcher->wakeUp();
}