码迷,mamicode.com
首页 > 其他好文 > 详细

Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)

时间:2015-11-09 23:52:26      阅读:622      评论:0      收藏:0      [点我收藏+]

标签:

Qt中事件分发源代码剖析

 

Qt中事件传递顺序:

在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的。
下面举例说明:

1)首先看看下面一段示例代码:

[cpp] view plaincopy技术分享技术分享
 
  1. int main(int argc, char *argv[])  
  2. {  
  3.     QApplication a(argc, argv);  
  4.     MouseEvent w;  
  5.     w.show();  
  6.       
  7.     return a.exec();
  8. }  

2)a.exec进入事件循环,调用的是QApplication::exec();

[cpp] view plaincopy技术分享技术分享
 
  1. int QApplication::exec()  
  2. {  
  3.     return <span style="color:#ff6666;">QGuiApplication::exec();</span>  
  4. }  

3)QApplication::exec()调用的是QGuiApplication::exec();

[cpp] view plaincopy技术分享技术分享
 
  1. int QGuiApplication::exec()  
  2. {  
  3. #ifndef QT_NO_ACCESSIBILITY  
  4.     QAccessible::setRootObject(qApp);  
  5. #endif  
  6.     return QCoreApplication::exec();
  7. }  

4)QGuiApplication::exec()调用的是QCoreApplication::exec();

[cpp] view plaincopy技术分享技术分享
 
  1. int QCoreApplication::exec()  
  2. {  
  3.     if (!QCoreApplicationPrivate::checkInstance("exec"))  
  4.         return -1;  
  5.   
  6.   
  7.     QThreadData *threadData = self->d_func()->threadData;  
  8.     if (threadData != QThreadData::current()) {  
  9.         qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());  
  10.         return -1;  
  11.     }  
  12.     if (!threadData->eventLoops.isEmpty()) {  
  13.         qWarning("QCoreApplication::exec: The event loop is already running");  
  14.         return -1;  
  15.     }  
  16.   
  17.   
  18.     threadData->quitNow = false;  
  19.     QEventLoop eventLoop;  
  20.     self->d_func()->in_exec = true;  
  21.     self->d_func()->aboutToQuitEmitted = false;  
  22.     int returnCode = eventLoop.exec();
  23.     threadData->quitNow = false;  
  24.     if (self) {  
  25.         self->d_func()->in_exec = false;  
  26.         if (!self->d_func()->aboutToQuitEmitted)  
  27.             emit self->aboutToQuit(QPrivateSignal());  
  28.         self->d_func()->aboutToQuitEmitted = true;  
  29.         sendPostedEvents(0, QEvent::DeferredDelete);  
  30.     }  
  31.   
  32.   
  33.     return returnCode;  
  34. }  

5)QCoreApplication::exec()调用eventLoop.exec()进行事件循环;

[cpp] view plaincopy技术分享技术分享
 
  1. int QEventLoop::exec(ProcessEventsFlags flags)  
  2. {  
  3.     Q_D(QEventLoop);  
  4.     //we need to protect from race condition with QThread::exit  
  5.     QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);  
  6.     if (d->threadData->quitNow)  
  7.         return -1;  
  8.   
  9.   
  10.     if (d->inExec) {  
  11.         qWarning("QEventLoop::exec: instance %p has already called exec()", this);  
  12.         return -1;  
  13.     }  
  14.   
  15.   
  16.     struct LoopReference {  
  17.         QEventLoopPrivate *d;  
  18.         QMutexLocker &locker;  
  19.   
  20.   
  21.         bool exceptionCaught;  
  22.         LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)  
  23.         {  
  24.             d->inExec = true;  
  25.             d->exit = false;  
  26.             ++d->threadData->loopLevel;  
  27.             d->threadData->eventLoops.push(d->q_func());  
  28.             locker.unlock();  
  29.         }  
  30.   
  31.   
  32.         ~LoopReference()  
  33.         {  
  34.             if (exceptionCaught) {  
  35.                 qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"  
  36.                          "exceptions from an event handler is not supported in Qt. You must\n"  
  37.                          "reimplement QApplication::notify() and catch all exceptions there.\n");  
  38.             }  
  39.             locker.relock();  
  40.             QEventLoop *eventLoop = d->threadData->eventLoops.pop();  
  41.             Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");  
  42.             Q_UNUSED(eventLoop); // --release warning  
  43.             d->inExec = false;  
  44.             --d->threadData->loopLevel;  
  45.         }  
  46.     };  
  47.     LoopReference ref(d, locker);  
  48.   
  49.   
  50.     // remove posted quit events when entering a new event loop  
  51.     QCoreApplication *app = QCoreApplication::instance();  
  52.     if (app && app->thread() == thread())  
  53.         QCoreApplication::removePostedEvents(app, QEvent::Quit);  
  54.   
  55.   
  56.     while (!d->exit)  
  57.         processEvents(flags | WaitForMoreEvents | EventLoopExec);  
  58.   
  59.   
  60.     ref.exceptionCaught = false;  
  61.     return d->returnCode;  
  62. }  

6)eventLoop.exec()调用QCoreApplication的processEvents进行事件分发;

7)调用notify进行分发

QCoreApplication::sendEvent、QCoreApplication::postEvent和QCoreApplication::sendPostedEvents都调用notify进行事件分发;

[cpp] view plaincopy技术分享技术分享
 
  1. bool QCoreApplication::notify(QObject *receiver, QEvent *event)  
  2. {  
  3.     Q_D(QCoreApplication);  
  4.     // no events are delivered after ~QCoreApplication() has started  
  5.     if (QCoreApplicationPrivate::is_app_closing)  
  6.         return true;  
  7.   
  8.   
  9.     if (receiver == 0) {                        // serious error  
  10.         qWarning("QCoreApplication::notify: Unexpected null receiver");  
  11.         return true;  
  12.     }  
  13.   
  14.   
  15. #ifndef QT_NO_DEBUG  
  16.     d->checkReceiverThread(receiver);  
  17. #endif  
  18.   
  19.   
  20.     return receiver->isWidgetType() ? false :<span style="color:#ff6666;"> d->notify_helper</span>(receiver, event);  
  21. }  

8)notify调用notify_helper进行事件分发;

[cpp] view plaincopy技术分享技术分享
 
  1. bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)  
  2. {  
  3.     // send to all application event filters  
  4.     if (sendThroughApplicationEventFilters(receiver, event))  
  5.         return true;  
  6.     // send to all receiver event filters  
  7.     if (sendThroughObjectEventFilters(receiver, event))  
  8.         return true;  
  9.     // deliver the event  
  10.     return receiver->event(event);  
  11. }  

9)从上面第8步的代码可以看出事件传递

传递的顺序是:首先传递给全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象。

 

http://blog.csdn.net/chenlong12580/article/details/25009095

Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)

标签:

原文地址:http://www.cnblogs.com/findumars/p/4951625.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!