QT---之QApplication与图形界面的联系

QApplication是程序,MainWindow是窗口,一个程序可以有多个从窗口。它的主要作用是

     1. QApplication通过exec()函数与MainWindow建立连接,而exec()函数里是

     通过调用底层的QCoreApplication,QEventLoop与QGuiApplication类与MainWindow建立联系,可能是因为前者使用MainWindow里某些static变量,从而导致凡是继承MainWindow的类,都与QApplication进行关联

     2. QApplication 类管理图形用户界面应用程序的控制流和主要设置

      它包含主事件循环,其中来自窗口系统和其它资源的所有事件被处理和调度。它也处理应用程序的初始化和结束,并且提供对话管理。它也处理绝大多数系统范围和应用程序范围的设置

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CalculatorTest w;
    w.show();
    return a.exec();
}

无意中发现一篇博客讲了QT事件源代码,看了半天看不懂,所以就加一下注释再理解一下

(1)第一步:

int main(int argc, char *argv[])  
{  
    QApplication a(argc, argv);  
    MouseEvent w;  
    w.show();  
      
    return <span style="color:#ff6666;">a.exec();</span>  

(2)第二步: 调用QGuiApplication的exec() ,是QApplication的父类

int QApplication::exec()  
{  
    return <span style="color:#ff6666;">QGuiApplication::exec();</span>  
}

(3)第三步:调用QCoreApplication的exec() ,是QGuiApplication的父类

int QGuiApplication::exec()  
{  
    #ifndef QT_NO_ACCESSIBILITY  
    QAccessible::setRootObject(qApp);   设置全APP里cation为根对象
    #endif  
    return <span style="color:#ff6666;">QCoreApplication::exec();</span>  
}  

(4)第四步:调用QEventLoop的exec()

int QCoreApplication::exec()  

{  
    if (!QCoreApplicationPrivate::checkInstance("exec"))  //如果在执行状态,则返回错误
        return -1;  
  
    QThreadData *threadData = self->d_func()->threadData; //返回主线程的线程id  
    if (threadData != QThreadData::current()) {  //当前线程和主线程的id不一样。则报错显示当前线程类的不是从主线程调用的
        qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());  
        return -1;  
    }  
    if (!threadData->eventLoops.isEmpty()) {  //判断当前事件循环不是空的,则报错
        qWarning("QCoreApplication::exec: The event loop is already running");  
        return -1;  
    }  
  
    threadData->quitNow = false; //设置主线程的立即停止位false  
    QEventLoop eventLoop;        //定义新的事件循环  
    self->d_func()->in_exec = true;  //将当前的事件循环的(正在执行置为true),这样当再次执行改程序时,可判断当前正在执行状态中,
便可在第一个if中返回
    self->d_func()->aboutToQuitEmitted = false; //将事件循环的将要停止发射设置为false,使得可以发射信号 
    int returnCode = <span style="color:#ff6666;">eventLoop.exec();</span>  //定义返回字显示的颜色格式
    threadData->quitNow = false;  //当事件循环执行完后,再次将立即停止定义为false
    if (self) {  
        self->d_func()->in_exec = false;//将执行状态设置为false,使得后续的事件可以继续执行 
        if (!self->d_func()->aboutToQuitEmitted)  //如果此状态为false,则重新发送消息停止的消息
            emit self->aboutToQuit(QPrivateSignal());  
        self->d_func()->aboutToQuitEmitted = true;  //将状态停止发送状态置为true
        sendPostedEvents(0, QEvent::DeferredDelete);  //投递延时delete的事件
    }  
  
    return returnCode;  


(5)第五步:进入事件循环
int QEventLoop::exec(ProcessEventsFlags flags)  
{  
    Q_D(QEventLoop);     // 不知道啥作用
    //we need to protect from race condition with QThread::exit  获取当前主线程的锁
    QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);  
    
    if (d->threadData->quitNow)//如果线程的状态为停止,则返回  
        return -1;  
  
  
    if (d->inExec) {判断主线程已在执行状态,则返回
        qWarning("QEventLoop::exec: instance %p has already called exec()", this);  
        return -1;  
    }  
  
  
    struct LoopReference {  //一个结构体:
        QEventLoopPrivate *d;     //定义事件循环指针
        QMutexLocker &locker;  //定义一个锁
  
  
        bool exceptionCaught;  //   定义
        LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)  
        {  
            d->inExec = true;     // 将事件循环状态设置为正在执行中
            d->exit = false;         // 将事件停止设置为false 

            ++d->threadData->loopLevel;   //将当前事件的优先级加1

            d->threadData->eventLoops.push(d->q_func());  // 将事件加入线程事件循环中
            locker.unlock();  //   解锁
        }  
  
  
        ~LoopReference()  
        {  
            if (exceptionCaught) {  
                qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"  
                         "exceptions from an event handler is not supported in Qt. You must\n"  
                         "reimplement QApplication::notify() and catch all exceptions there.\n");  
            }  
            locker.relock();     //重新锁住
            QEventLoop *eventLoop = d->threadData->eventLoops.pop();   // 将最后一个事件pop出来  
            Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");   // 
            Q_UNUSED(eventLoop); // --release warning  
            d->inExec = false;                //将正在执行的标志位设置为false
            --d->threadData->loopLevel;  //将其事件个数(还是什么)减1????????????????
        }  
    };  
    LoopReference ref(d, locker);  
  
  
    // remove posted quit events when entering a new event loop  
    QCoreApplication *app = QCoreApplication::instance();  
    if (app && app->thread() == thread())                     //判断app的线程和事件线程是否为一个线程
        QCoreApplication::removePostedEvents(app, QEvent::Quit);  删除时间投递,并将其设置为停止  
  
  
    while (!d->exit)   //如果没有退出
        <span style="color:#ff6666;">processEvents</span>(flags | WaitForMoreEvents | EventLoopExec);  
  
  
    ref.exceptionCaught = false;  
    return d->returnCode;  

}   

(6)调用QCoreApplication的processEvents进行事件分发

(7)调用notify进行分发

bool QCoreApplication::notify(QObject *receiver, QEvent *event)  
{  
    Q_D(QCoreApplication);  
    // no events are delivered after ~QCoreApplication() has started  
    if (QCoreApplicationPrivate::is_app_closing)  
        return true;  
  
  
    if (receiver == 0) {                        // serious error  
        qWarning("QCoreApplication::notify: Unexpected null receiver");  
        return true;  
    }   
    #ifndef QT_NO_DEBUG  
    d->checkReceiverThread(receiver);  
   #endif   
    return receiver->isWidgetType() ? false :<span style="color:#ff6666;"> d->notify_helper</span>(receiver, event);  
}-

猜你喜欢

转载自blog.csdn.net/weixin_39609623/article/details/82985446