Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1695601
  • 博文数量: 584
  • 博客积分: 13857
  • 博客等级: 上将
  • 技术积分: 11883
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-16 09:34

分类: C/C++

2011-01-24 00:02:22

版权声明

请尊重原创作品。转载请保持文章完整性,并以超链接形式注明原始作者“”和主站点地址,方便其他朋友提问和指正。 

 

QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

QT源码解析(二)深入剖析QT元对象系统和信号槽机制

QT源码解析(三)深入剖析QT元对象系统和信号槽机制(续)

QT源码解析(四)剖析Qt的事件机制原理

QT源码解析(五)QLibrary跨平台调用动态库的实现

QT源码解析(六)Qt信号槽机制与事件机制的联系

QT源码解析(七)Qt创建窗体的过程

QT源码解析(八)Qt是如何处理windows消息的

QT源码解析(九)解析QDateTime 

在用Qt写Gui程序的时候,在main函数里面最后依据都是app.exec();很多书上对这句的解释是,使Qt程序进入消息循环。下面我们就到exec()函数内部,来看一下他的实现原理。

首先来到QTDIR\src\corelib\kernel\qcoreapplication.cpp


  1. int QCoreApplication::exec()
  2. {
  3.     if (!QCoreApplicationPrivate::checkInstance("exec"))
  4.         return -1;
  5.     //获取线程数据
  6.     QThreadData *threadData = self->d_func()->threadData;
  7.     //判断是否在主线程创建
  8.     if (threadData != QThreadData::current()) {
  9.         qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
  10.         return -1;
  11.     }
  12.     //判断eventLoop是否已经创建
  13.     if (!threadData->eventLoops.isEmpty()) {
  14.         qWarning("QCoreApplication::exec: The event loop is already running");
  15.         return -1;
  16.     }

  17.     threadData->quitNow = false;
  18.     QEventLoop eventLoop;
  19.     self->d_func()->in_exec = true;
  20.     //创建eventLoop
  21.     int returnCode = eventLoop.exec();
  22.     threadData->quitNow = false;
  23.     if (self) {
  24.         self->d_func()->in_exec = false;
  25.         //退出程序
  26.         emit self->aboutToQuit();
  27.         sendPostedEvents(0, QEvent::DeferredDelete);
  28.     }
  29.     return returnCode;
  30. }

  1. 再来到qeventloop.cpp中。
  2. int QEventLoop::exec(ProcessEventsFlags flags)
  3. {
  4.     Q_D(QEventLoop);
  5.     if (d->threadData->quitNow)
  6.         return -1;
  7.     //已经调用过exec了。
  8.     if (d->inExec) {
  9.         qWarning("QEventLoop::exec: instance %p has already called exec()", this);
  10.         return -1;
  11.     }
  12.     d->inExec = true;
  13.     d->exit = false;
  14.     ++d->threadData->loopLevel;
  15.     //将事件类对象压入线程结构体中
  16.     d->threadData->eventLoops.push(this);

  17.     // remove posted quit events when entering a new event loop
  18.     // 这句不用翻译了把!
  19.     if (qApp->thread() == thread())
  20.         QCoreApplication::removePostedEvents(qApp, QEvent::Quit);

  21. #if defined(QT_NO_EXCEPTIONS)
  22.     while (!d->exit)
  23.         //这里才是关键,我们还要继续跟踪进去。
  24.         processEvents(flags | WaitForMoreEvents);
  25. #else
  26.     try {
  27.         while (!d->exit)
  28.             processEvents(flags | WaitForMoreEvents);
  29.     } catch (...) {
  30.         //如果使用了EXCEPTION,则继续对下一条时间进行处理。
  31.         qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
  32.                  "exceptions from an event handler is not supported in Qt. You must\n"
  33.                  "reimplement QApplication::notify() and catch all exceptions there.\n");
  34.         throw;
  35.     }
  36. #endif
  37.     //退出eventloop前,将时间对象从线程结构中取出。
  38.     QEventLoop *eventLoop = d->threadData->eventLoops.pop();
  39.     Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
  40.     Q_UNUSED(eventLoop); // --release warning

  41.     d->inExec = false;
  42.     --d->threadData->loopLevel;
  43.     //退出事件循环。
  44.     return d->returnCode;
  45. }

  46. 来到了processEvents函数:
  47. bool QEventLoop::processEvents(ProcessEventsFlags flags)
  48. {
  49.     Q_D(QEventLoop);
  50.     //判断事件分派器是否为空。
  51.     if (!d->threadData->eventDispatcher)
  52.         return false;
  53.     if (flags & DeferredDeletion)
  54.         QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
  55.     //调用不同平台下的事件分派器来处理事件。
  56.     return d->threadData->eventDispatcher->processEvents(flags);
  57. }

  58. processEvents是在QAbstractEventDispatcher类中定义的纯虚方法。在QEventDispatcherWin32类有processEvents的实现。



  1. bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
  2. {
  3.     Q_D(QEventDispatcherWin32);
  4.     //内部数据创建。registerClass注册窗口类,createwindow创建窗体。
  5.     //注册socket notifiers,启动所有的normal timers
  6.     if (!d->internalHwnd)
  7.         createInternalHwnd();

  8.     d->interrupt = false;
  9.     emit awake();

  10.     bool canWait;
  11.     bool retVal = false;
  12.     do {
  13.         QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);

  14.         DWORD waitRet = 0;
  15.         HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
  16.         QVarLengthArray<MSG> processedTimers;
  17.         while (!d->interrupt) {
  18.             DWORD nCount = d->winEventNotifierList.count();
  19.             Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);

  20.             MSG msg;
  21.             bool haveMessage;

  22.             if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
  23.                 // process queued user input events处理用户输入事件,放入队列中。
  24.                 haveMessage = true;
  25.                 msg = d->queuedUserInputEvents.takeFirst();
  26.             } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
  27.                 // process queued socket events 处理socket事件,放入队列中。
  28.                 haveMessage = true;
  29.                 msg = d->queuedSocketEvents.takeFirst();
  30.             } else {
  31.                 //从消息队列中取消息,同PeekMessage
  32.                 haveMessage = winPeekMessage(&msg, 0, 0, 0, PM_REMOVE);
  33.                 if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
  34.                     && ((msg.message >= WM_KEYFIRST
  35.                          && msg.message <= WM_KEYLAST)
  36.                         || (msg.message >= WM_MOUSEFIRST
  37.                             && msg.message <= WM_MOUSELAST)
  38.                         || msg.message == WM_MOUSEWHEEL)) {
  39.                     // queue user input events for later processing
  40.                     haveMessage = false;
  41.                     d->queuedUserInputEvents.append(msg);
  42.                 }
  43.                 if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
  44.                     && (msg.message == WM_USER && msg.hwnd == d->internalHwnd)) {
  45.                     // queue socket events for later processing
  46.                     haveMessage = false;
  47.                     d->queuedSocketEvents.append(msg);
  48.                 }
  49.             }
  50.  


阅读(2210) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~