我的问题是关于在QT中使用类的一般性问题。我有两个主要问题。
问题1) 它在QT内部是如何工作的(我的主要关注点是为什么一个QEventLoop对象的执行不会阻塞QT应用程序主循环 - [编辑3]此最后一条评论是不正确的,请参见以下答案)。详见下文。
问题2) 除了阻止之外,它还有其他用途吗?似乎我只能遇到使用QEventLoop等待的示例。它可以用于其他目的吗?例如,我们是否可以想象将特定事件的处理委托给本地QEventLoop而不是主应用程序循环?(不确定这个问题是否有意义)
问题1的发展:
我对QT主事件循环的基本工作原理的理解如下。应用程序主事件循环(QCoreApplication::exec())从队列中抓取一个QEvent“E”,并将其分派给它决定事件应该去哪个QObject“A”(例如,在鼠标左键按下时QWidget的位置和Z值)如果我们假设对象“A”正在使用事件“E”,那么该对象的事件方法(还有其他方便的方法和事件过滤器,但让我们假设事件方法在我们的情况下处理事件)被调用-此处发生与对象“A”相关的一些处理-并返回true。然后,QT主事件循环开始处理队列中的下一个事件,以此类推。
但是,如果在调用对象“A”的事件方法时出现了阻塞,我会期望主应用程序循环被阻塞,因为它等待接收器(对象“A”)的事件方法返回...例如,如果事件的处理最终调用我们创建永远不会退出的本地QEventLoop的对象“A”的一个方法,那么我的期望是整个应用程序将停止,并且不再处理任何事件,直到本地QEventLoop退出,而对象“A”的事件方法返回。否则,这是不正确的,因为我可以看到本地QEventLoop不会阻塞应用程序主事件循环... 有人能给我更多关于本地QEventLoop如何工作的见解吗?[编辑3]请参见以下答案,本地事件循环处理事件
通过上面的例子,我有一个简单的窗口,其中包含2个按钮:"按钮1"(显示其状态:已选中或未选中)和“按钮2”(在点击时触发本地QEventLoop)。 当我点击按钮2时,它在“loop.exec()”处阻塞,即第二个调试消息永远不会输出。然后,我期望主应用程序循环也被阻塞了,但我认为它并没有被阻塞,因为我仍然可以点击“按钮1”,以显示其状态(已选中或未选中),这意味着鼠标事件仍由主应用程序事件循环处理。
问题1) 它在QT内部是如何工作的(我的主要关注点是为什么一个QEventLoop对象的执行不会阻塞QT应用程序主循环 - [编辑3]此最后一条评论是不正确的,请参见以下答案)。详见下文。
问题2) 除了阻止之外,它还有其他用途吗?似乎我只能遇到使用QEventLoop等待的示例。它可以用于其他目的吗?例如,我们是否可以想象将特定事件的处理委托给本地QEventLoop而不是主应用程序循环?(不确定这个问题是否有意义)
问题1的发展:
我对QT主事件循环的基本工作原理的理解如下。应用程序主事件循环(QCoreApplication::exec())从队列中抓取一个QEvent“E”,并将其分派给它决定事件应该去哪个QObject“A”(例如,在鼠标左键按下时QWidget的位置和Z值)如果我们假设对象“A”正在使用事件“E”,那么该对象的事件方法(还有其他方便的方法和事件过滤器,但让我们假设事件方法在我们的情况下处理事件)被调用-此处发生与对象“A”相关的一些处理-并返回true。然后,QT主事件循环开始处理队列中的下一个事件,以此类推。
但是,如果在调用对象“A”的事件方法时出现了阻塞,我会期望主应用程序循环被阻塞,因为它等待接收器(对象“A”)的事件方法返回...例如,如果事件的处理最终调用我们创建永远不会退出的本地QEventLoop的对象“A”的一个方法,那么我的期望是整个应用程序将停止,并且不再处理任何事件,直到本地QEventLoop退出,而对象“A”的事件方法返回。否则,这是不正确的,因为我可以看到本地QEventLoop不会阻塞应用程序主事件循环... 有人能给我更多关于本地QEventLoop如何工作的见解吗?[编辑3]请参见以下答案,本地事件循环处理事件
---- EDIT 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个按钮:"按钮1"(显示其状态:已选中或未选中)和“按钮2”(在点击时触发本地QEventLoop)。 当我点击按钮2时,它在“loop.exec()”处阻塞,即第二个调试消息永远不会输出。然后,我期望主应用程序循环也被阻塞了,但我认为它并没有被阻塞,因为我仍然可以点击“按钮1”,以显示其状态(已选中或未选中),这意味着鼠标事件仍由主应用程序事件循环处理。
QEventLoop
会阻塞主应用程序循环。 - Dmitry Sazonov