Qtの事件の処理のメカニズムの2を浅く議論します
転載先:http://blog.csdn.net/changsheng230/article/details/6092978
上記では、Qtフレームワークのイベント処理メカニズム:イベントの発生、配布、受け入れ、処理を紹介し、ウィンドウシステムのマウスクリックQWidgetを例に、コードを分析し、QtフレームワークがどのようにEvent Loop処理を通じてメッセージキューサイクルに入り、どのようにプラットフォーム関連の関数に一歩一歩委任されるかを分析した.パッケージングユーザ入力イベントはウィンドウシステム処理に渡され、関数呼び出しスタックは以下の通りである. main(int, char **) QApplication::exec() QCoreApplication::exec() QEventLoop::exec(ProcessEventsFlags ) QEventLoop::processEvents(ProcessEventsFlags ) QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags)
ここでは、Qt appがウィンドウシステムでコールバックされた後、イベントがQLPplicationを介して最終イベントの受信者と処理者QWidget::event、(QWidgetはObjectを継承し、その虚関数eventを再ロードする)にどのように配布されるかについて説明します.以下のすべての議論はソースコードに埋め込まれます. QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) bool QETWidget::translateMouseEvent(const MSG &msg) bool QApplicationPrivate::sendMouseEvent(...) inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event) bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) bool QApplication::notify(QObject *receiver, QEvent *e) bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) bool QWidget::event(QEvent *event)
上記では、Qtフレームワークのイベント処理メカニズム:イベントの発生、配布、受け入れ、処理を紹介し、ウィンドウシステムのマウスクリックQWidgetを例に、コードを分析し、QtフレームワークがどのようにEvent Loop処理を通じてメッセージキューサイクルに入り、どのようにプラットフォーム関連の関数に一歩一歩委任されるかを分析した.パッケージングユーザ入力イベントはウィンドウシステム処理に渡され、関数呼び出しスタックは以下の通りである.
ここでは、Qt appがウィンドウシステムでコールバックされた後、イベントがQLPplicationを介して最終イベントの受信者と処理者QWidget::event、(QWidgetはObjectを継承し、その虚関数eventを再ロードする)にどのように配布されるかについて説明します.以下のすべての議論はソースコードに埋め込まれます.
// ( Section 7) Section 2-1:
QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
...
// message Qt
if (qt_is_translatable_mouse_event(message)) {
if (QApplication::activePopupWidget() != 0) {
POINT curPos = msg.pt;
// QWidget , main widget
QWidget* w = QApplication::widgetAt(curPos.x, curPos.y);
if (w)
widget = (QETWidget*)w;
}
if (!qt_tabletChokeMouse) {
// , 。Windows Qt Widget
// => Section 2-2
result = widget->translateMouseEvent(msg);
...
}
// Section 2-2 $QTDIR/src/gui/kernel/qapplication_win.cpp
// Windows , windows 、 QApplication QMouseEvent,QWidget.
bool QETWidget::translateMouseEvent(const MSG &msg)
{
//..
// sendMouseEvent
// widget ; e QMouseEvent
// ==> Section 2-3
res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, qt_last_mouse_receiver);
}
// Section 2-3 $QTDIR/src/gui/kernel/qapplication.cpp
bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
QWidget *alienWidget, QWidget *nativeWidget,
QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
bool spontaneous)
{
//
//MouseEvent spontaneous, sendSpontaneousEvent。 sendSpontaneousEvent() sendEvent , QEvent spontaneous 。 spontaneous : , 。 MousePress ( Section 1~ Section 7),
spontaneous
if (spontaneous)
result = QApplication::sendSpontaneousEvent(receiver, event); ==〉Section 2-4
else
result = QApplication::sendEvent(receiver, event);
}
// Section 2-4 C:/Qt/4.7.1-Vs/src/corelib/kernel/qcoreapplication.h
inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
{
// event
// 2-5 QCoreApplication::notifyInternal
if (event) event->spont = true; return self ? self->notifyInternal(receiver, event) : false;
}
// Section 2-5: $QTDIR/gui/kernel/qapplication.cpp
bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
{
// Qt Jambi (QT Java ) QSA (QT Script for Application)
...
// Qt , receiver->d_func()->threadData QThreadData::current()。 , Event Loop
QObjectPrivate *d = receiver->d_func();
QThreadData *threadData = d->threadData;
++threadData->loopLevel;
bool returnValue;
QT_TRY {
// , QCoreApplication::nofity() ==> Section 2-6
returnValue = notify(receiver, event);
} QT_CATCH (...) {
--threadData->loopLevel;
QT_RETHROW;
}
}
// Section 2-6: $QTDIR/gui/kernel/qapplication.cpp
// QCoreApplication::notify QApplication::notify Qt ,Qt : notify 。
bool QApplication::notify(QObject *receiver, QEvent *e)
{
// , Switch,Case
..
switch ( e->type())
{
...
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
...
// (d ) ==> Section 2-7
res = d->notify_helper(w, w == receiver ? mouse : &me);
e->spont = false;
break;
}
...
}
// Section 2-7: $QTDIR/gui/kernel/qapplication.cpp
bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
{
...
// , Event Filters. 。
// 。 QObject::eventFilter() , , 。 , 。 , 。
if (sendThroughObjectEventFilters(receiver, e))
return true;
// receiver => Section 2-8
bool consumed = receiver->event(e);
e->spont = false;
}
// Section 2-8 $QTDIR/gui/kernel/qwidget.cpp
// QApplication notify notify_helper, QObject - QWidget.
bool QWidget::event(QEvent *event)
{
...
switch(event->type()) {
case QEvent::MouseButtonPress:
// Don't reset input context here. Whether reset or not is
// a responsibility of input method. reset() will be
// called by mouseHandler() of input method if necessary
// via mousePressEvent() of text widgets.
#if 0
resetInputContext();
#endif
//mousePressEvent ,QWidget mousePress
mousePressEvent((QMouseEvent*)event);
break;
}