c++qtqeventloop

How local QEventLoop works


My question is general and related to the use of the class QEventLoop in QT. I have two main questions about it.

question 1) how it works internally inside QT (my main concern is why the execution of a QEventLoop object is not blocking the QT application main loop - [EDIT 3] this last comment is not true, see answers below).
See below for details.

question 2) Has it another purpose except than blocking ? It seems I can only come across examples where QEventLoop is used for waiting purpose.
Can it be used for other purposes ? Like could we imagine delgating the processing of specific events from the main application loop to a local QEventLoop ? (not sure if this question makes any sense)

Development of question 1):

My understanding of how the QT main event loop basically works is the following. The application main event loop (QCoreApplication::exec()) grabs an QEvent "E" from the queue, and dispatches it to the QObject "A" it decides the event shall go to (for example, the position and Z-value of a QWidget in case of a mouse-left press). If we assume object "A" is using the event "E", the event method of that object (there are other convenience methods and event filters, but let's assume the event method deals with the event in our case) is called - some processing related to object "A" happens here - and returns true. Then, the QT main event loop start processing the next event in the queue, and so on.

However, IF there is is something blocking in the call of the event method of object "A", I would expect the main application loop to be blocked since it waits for the event method of the receiver (object "A") to return...
So for example, if the processing of an event ends up calling a method of object "A" where we create a local QEventLoop that we never quit, my expectation would be that the entire application is stopped and no more events are processed, until the local QEventLoop is quitted, and the event method of object "A" returns.
Otherwise, this is not true, as I could see that a local QEventLoop is not blocking the application main Event Loop...
Could someone give me more insight on how the local QEventLoop works ? [EDIT 3] see answer's below, the local event loop processes events

---- EDIT 1 ----

I am sorry if I am not clear, this is actually quite difficult to explain with words so below is a small code snippet to better illustrate my question 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();
    }

With the example above, I have a simple window with 2 buttons, "button 1" (which displays its state: checked or not checked) and "button 2" (which triggers a local QEventLoop when clicked). When I click on button 2, it blocks at "loop.exec()", i.e. the second debug message is never output. Then, I would expect the main application loop to be blocked as well, however, i don't think it is as I can still click on "button 1" which displays its state (checked or not checked), meaning that mouse events are still processed by the main application event loop.


Solution

  • No, events are not processed by the main QApplication event loop. They are processed by loop, and dispatched to their usual places.

    The code as you have presented it has no means of ending loop. There is nothing stopping you from clicking button2 again, and having another loop within the two currently running (the first loop and the main QApplication loop).

    If you attach a debugger to your process, you will see a stack frame for each loop that is running