本地 QEventLoop 的工作原理

use*_*440 5 c++ qt qeventloop

我的问题是一般性的,与 QT 中QEventLoop类的使用有关。我对此有两个主要问题。

问题1)它在QT内部如何工作(我主要关心的是为什么QEventLoop对象的执行不会阻塞QT应用程序主循环 - [编辑3]最后一条评论不正确,请参阅下面的答案)。
详情请参阅下文。

问题2)除了阻塞之外还有其他目的吗?看来我只能遇到QEventLoop用于等待目的的例子。
可以用于其他目的吗?就像我们可以想象将特定事件的处理从主应用程序循环委托给本地 QEventLoop 吗?(不确定这个问题是否有意义)

问题1)的展开:

我对 QT 主事件循环基本工作原理的理解如下。应用程序主事件循环(QCoreApplication::exec() )从队列中获取QEvent “E”,并将其分派到它决定事件应前往的QObject “A”(例如,事件的位置和 Z 值)如果按下鼠标左键则为QWidget ) 。如果我们假设对象“A”正在使用事件“E”,则调用该对象的事件方法(还有其他便利方法和事件过滤器,但我们假设事件方法处理我们案例中的事件) - 一些处理与对象“A”相关的事件发生在这里 - 并返回 true。然后,QT主事件循环开始处理队列中的下一个事件,依此类推。

但是,如果对象“A”的事件方法的调用中存在某些阻塞,我希望主应用程序循环被阻塞,因为它等待接收者(对象“A”)的事件方法返回。 ..
例如,如果事件的处理最终调用对象“A”的方法,我们在其中创建一个永远不会退出的本地QEventLoop,我的期望是整个应用程序停止并且不再处理任何事件,直到本地QEventLoop退出,对象“A”的事件方法返回。
否则,这是不正确的,因为我可以看到本地QEventLoop没有阻止应用程序主事件循环...
有人可以让我更深入地了解本地QEventLoop如何工作吗? [编辑3]参见下面的答案,本地事件循环处理事件

---- 编辑 1 ----

如果我不清楚,我很抱歉,这实际上很难用语言解释,所以下面是一个小代码片段,以更好地说明我的问题 1

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
Run Code Online (Sandbox Code Playgroud)

主窗口.cpp

#include "mainwindow.h"
#include <QPushButton>
#include <QEventLoop>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QPushButton* button1 = new QPushButton(this);
    button1->setText("button 1");
    button1->setCheckable(true);

    QPushButton* button2 = new QPushButton(this);
    button2->setText("button 2");
    button2->move(0,50);

    connect(button1,&QPushButton::toggled,button1,[button1](bool toggled){
        button1->setText(toggled ? "CHECKED" : "NOT CHECKED");
    });

    connect(button2,&QPushButton::clicked,button2,[](){
        QEventLoop loop;
        qInfo() << "Before loop exec";
        loop.exec();
        qInfo() << "After loop exec";
    });
}

MainWindow::~MainWindow()
{
}
Run Code Online (Sandbox Code Playgroud)

主程序

#include "mainwindow.h"
#include <QApplication>

    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();

        return a.exec();
    }
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,我有一个带有 2 个按钮的简单窗口,“按钮 1”(显示其状态:选中或未选中)和“按钮 2”(单击时触发本地 QEventLoop)。当我单击按钮 2 时,它会阻塞在“loop.exec()”处,即永远不会输出第二条调试消息。然后,我希望主应用程序循环也被阻止,但是,我不认为这是因为我仍然可以单击显示其状态(选中或未选中)的“按钮 1”,这意味着鼠标事件是仍然由主应用程序事件循环处理。

Cal*_*eth 5

不,事件不是主 QApplication 事件循环处理的。它们由 处理loop并发送到其通常的地点。

您所提供的代码无法结束loop。没有什么可以阻止您button2再次单击,并loop在当前运行的两个循环(第一个loop和主 QApplication 循环)中再单击一次。

如果将调试器附加到进程,您将看到正在运行的每个循环的堆栈帧