本地QEventLoop的工作原理

时间:2018-05-21 14:21:36

标签: c++ qt qeventloop

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

问题1)它在QT内部是如何工作的(我主要担心的是 QEventLoop 对象的执行没有阻止QT应用程序主循环 - [编辑3]这最后的评论不正确,见下面的答案) 有关详细信息,请参阅下文。

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

开发问题1):

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

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

----编辑1 ----

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

mainwindow.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

mainwindow.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()
{
}

的main.cpp

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

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

        return a.exec();
    }

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

1 个答案:

答案 0 :(得分:3)

不,主QApplication事件循环处理事件。它们由loop处理,并发送到他们通常的位置。

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

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