我的问题是一般性的,与QT中使用QEventLoop类有关。我有两个主要问题。
问题 1(它在 QT 内部如何工作(我主要关心的是为什么执行 QEventLoop对象不会阻塞 QT 应用程序主循环 -[EDIT 3] 这最后一条评论是不正确的,请参阅下面的答案(。
详情见下文。
问题2(除了阻止之外还有其他目的吗?似乎我只能遇到将QEventLoop用于等待目的的示例。
它可以用于其他目的吗?就像我们可以想象将特定事件的处理从主应用程序循环挖掘到本地 QEventLoop 吗?(不确定这个问题是否有任何意义(
问题1的发展(:
我对QT主事件循环基本工作原理的理解如下。应用程序主事件循环 (QCoreApplication::exec((( 从队列中获取一个QEvent"E",并将其调度到QObject"A",它决定事件应该去(例如,在鼠标左按的情况下QWidget的位置和 Z 值(。如果我们假设对象"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
主窗口.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()
{
}
主.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
在上面的例子中,我有一个简单的窗口,有 2 个按钮,"按钮 1"(显示其状态:选中或未选中(和"按钮 2"(单击时触发本地 QEventLoop(。 当我单击按钮 2 时,它会在"loop.exec(("处阻塞,即永远不会输出第二条调试消息。然后,我希望主应用程序循环也会被阻止,但是,我认为不是这样,因为我仍然可以单击显示其状态(选中或未选中(的"按钮 1",这意味着鼠标事件仍然由主应用程序事件循环处理。
不,主 QApplication 事件循环不处理事件。它们由loop
处理,并被派往它们通常的地方。
您呈现的代码无法结束loop
。没有什么能阻止您再次单击button2
,并在当前运行的两个loop
(第一个loop
和主 QApplication 循环(中具有另一个。
如果将调试器附加到进程,您将看到正在运行的每个循环的堆栈帧