QEventLoop 处理所有事件
Posted
技术标签:
【中文标题】QEventLoop 处理所有事件【英文标题】:QEventLoop process all events 【发布时间】:2018-09-06 09:45:03 【问题描述】:我有一个菜单屏幕,必须在登录屏幕关闭之前更新。 代码类似于下面的代码;
emit updateMainMenuAccordingToUserRights;
QCoreApplication::processEvents();
emit jumpMainMenu();
问题是“我如何确定所有事件都已处理?”。因为由 updateMainMenuAccordingToUserRights 信号触发的一些槽将新事件添加到事件循环以更新视图组件。在跳转主菜单之前,我必须确保它已经更新。我搜索了一下,发现 QCoreApplication::processEvent 只处理循环一次。好的,这就是上面代码不起作用的原因。即使我尝试了一些 QEventLoop 方法,但无法解决这个问题。
感谢您的建议。
【问题讨论】:
您需要在主菜单中添加一个信号,一旦更新完成就会触发一个槽。在此插槽中,您发出函数调用jumpMainMenu
。
QEventLoop::WaitForMoreEvents
flag你试过了吗。
但就我而言,主菜单由小插件组成。主菜单不仅仅是一个对象。它正在被应用程序的一小部分更改(每个插件中都有一个用于 updateMainMenuAccordingToUserRights 的插槽)。所以,所有这些插槽都应该被执行。甚至这些插槽也可以自己添加新事件/发出信号。
@MohammadKanan 是的,我已经尝试过了。
必须强制事件循环意味着您可能正在做一些不推荐的事情,并且可以以更好的方式完成。我已经广泛使用 Qt 10 年了,我用它做了一些疯狂的复杂的事情,而且我从来不需要强制事件处理,一次也没有。
【参考方案1】:
我有一个菜单屏幕,必须在登录屏幕关闭之前更新
完全没有 - 这是一个 XY 问题。换句话说:你的设计是错误的。您需要以某种方式轻轻地将登录屏幕耦合到菜单屏幕,以便菜单屏幕在登录屏幕关闭之前获取它需要更新自身的信息。在那之后的任何时候,登录屏幕确实可以关闭。
您很可能将登录屏幕 与登录控制器 紧密耦合,因此LoginScreen
类应该发出MenuScreen
将处理的事件。
您当前的信号名称表明屏幕之间的耦合非常紧密。您只需要一个信号:loginDone(const LoginData &)
,其中LoginData
是一个结构/类,其中包含有关登录用户等的信息。
那么,问题中的三行代码就变成了:
auto d = this->getLoginData();
emit loginDone(d);
close();
和
LoginData LoginScreen::getLoginData() const
LoginData d;
d.foo = this->foo();
d.bar = this->bar();
...
return d;
然后,一个函数(最好在控制器类中)将通过 LoginData
对象松散地将 LoginScreen
耦合到 MenuScreen
:
void setLoginDataOnMenu(const LoginData &data, MenuScreen *menu)
...
menu->show();
;
int main(int argc, char **argv)
QApplication appargc, argv;
LoginScreen login;
MenuScreen menu;
QObject::connect(&login, &LoginScreen::loginDone, &menu, [&](const LoginData &)
setLoginDataOnMenu(data, &menu);
);
login.show();
return app.exec();
;
理想情况下,您希望有一个单独的控制器类来实现逻辑,而不是在屏幕中。然后LoginScreen
和MenuScreen
可以是控制器公开的数据的视图。
【讨论】:
以上是关于QEventLoop 处理所有事件的主要内容,如果未能解决你的问题,请参考以下文章
关于Qt的事件循环以及QEventLoop的简单使用(QEventLoop::quit()能够终止事件循环,事件循环是可以嵌套的)