Как работает локальный QEventLoop

Мой вопрос общий и связан с использованием класса QEventLoop в QT. У меня есть два основных вопроса по этому поводу.

вопрос 1), как это работает внутри QT (моя основная проблема заключается в том, почему выполнение объекта QEventLoop не блокирует основной цикл приложения QT - [EDIT 3 ] последний комментарий не соответствует действительности, см. ответы ниже).
Подробнее см. ниже.

вопрос 2) Есть ли у него другая цель, кроме блокировки? Кажется, я могу встретить только примеры, где QEventLoop используется для целей ожидания.
Можно ли использовать его для других целей? Например, можем ли мы представить делегирование обработки определенных событий из основного цикла приложения в локальный цикл QEventLoop? (не уверен, что этот вопрос имеет смысл)

Развитие вопроса 1):

Мое понимание того, как в основном работает основной цикл событий QT, заключается в следующем. Основной цикл событий приложения (QCoreApplication::exec()) захватывает QEvent "E" из очереди и отправляет его в QObject "A" определяет, куда должно перейти событие (например, положение и Z-значение QWidget в случае нажатия левой кнопки мыши). Если мы предполагаем, что объект «A» использует событие «E», вызывается метод события этого объекта (существуют другие удобные методы и фильтры событий, но давайте предположим, что метод события имеет дело с событием в нашем случае) — некоторая обработка связанный с объектом "А" происходит здесь - и возвращает true. Затем основной цикл событий QT начинает обрабатывать следующее событие в очереди и так далее.

Тем не менее, ЕСЛИ что-то блокирует вызов метода события объекта "A", я ожидаю, что основной цикл приложения будет заблокирован, поскольку он ожидает метод события получателя (объект "A") для возврата...
Так, например, если обработка события завершается вызовом метода объекта "A", в котором мы создаем локальный QEventLoop, из которого никогда не выходим , я ожидаю, что все приложение будет остановлено и события больше не будут обрабатываться до тех пор, пока локальный QEventLoop не будет закрыт и метод события объекта "A" не вернется.
В противном случае это неверно, так как я видел, что локальный QEventLoop не блокирует основной цикл событий приложения...
Может ли кто-нибудь дать мне больше информации о том, как локальный QEventLoop работает? [EDIT 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();
    }

В приведенном выше примере у меня есть простое окно с двумя кнопками: «кнопка 1» (которая отображает ее состояние: отмечена или не отмечена) и «кнопка 2» (которая запускает локальный цикл QEventLoop при нажатии). Когда я нажимаю кнопку 2, она блокируется в "loop.exec()", т.е. второе отладочное сообщение никогда не выводится. Затем я ожидаю, что основной цикл приложения также будет заблокирован, однако я не думаю, что это так, поскольку я все еще могу нажать «кнопку 1», которая отображает ее состояние (проверено или не проверено), что означает, что события мыши все еще обрабатывается основным циклом событий приложения.


person user3722440    schedule 21.05.2018    source источник
comment
В чем проблема прочитать исходники? Кстати, вы ошибаетесь - QEventLoop блокирует основной цикл приложения.   -  person Dmitry Sazonov    schedule 21.05.2018
comment
@DmitrySazonov: Извините, я буду читать дальше, но я не смог найти много примеров QEventLoop в Интернете, плюс документ QT не очень подробно описывает использование этого класса, поэтому я задал вопрос. Возможно, я что-то упускаю, но в моем примере EDIT 1 локальный QEventLoop, похоже, не блокирует основной цикл событий приложения.   -  person user3722440    schedule 21.05.2018


Ответы (1)


Нет, события не обрабатываются основным циклом событий QApplication. Они обрабатываются loop и отправляются на свои обычные места.

Код, который вы представили, не имеет возможности закончить loop. Ничто не мешает вам щелкнуть button2 еще раз и получить еще один loop в двух запущенных в данный момент (первый loop и основной цикл QApplication).

Если вы подключите отладчик к вашему процессу, вы увидите кадр стека для каждого запущенного цикла.

person Caleth    schedule 21.05.2018
comment
Спасибо, Калет... Я был в замешательстве и думал, что локальный QEventLoop полностью независим от QApplication. Я понимаю, что это не так. - person user3722440; 22.05.2018