QT C++中如何等待另一个窗口关闭后再执行后续操作?
问题原因
你当前实现出现原窗口闪现后关闭的核心问题有3个:
- 手动调用
hide()、show()操作原窗口的显示状态,中间的本地事件循环阻塞可能导致原窗口的状态逻辑异常,甚至触发意料之外的关闭信号 - 弹出的
ClusterPostcoordination窗口没有设置Qt::WA_DeleteOnClose属性,关闭窗口时默认只是隐藏而非销毁对象,不会触发destroyed()信号,你写的本地QEventLoop可能出现退出时机异常 - 旧的
SIGNAL()/SLOT()信号槽语法没有编译期检查,如果连接失败会导致事件循环无法正常退出,后续逻辑执行时序混乱
现有代码修复方案
如果要保留你当前的实现逻辑,只需做3处修改即可解决问题:
try { // 删掉this->hide() 不需要隐藏原窗口 vector<ICD11> postcoordinations = dbhandler->QueryHasPostcoords(temp,ICD11cluster); if(!postcoordinations.empty()){ ClusterPostcoordination *cp = new ClusterPostcoordination(this,&temp,&postcoordinations,&ICD11cluster); // 父指针改成this,不要传nullptr cp->setAttribute(Qt::WA_DeleteOnClose); // 关闭窗口自动销毁对象 cp->setWindowModality(Qt::ApplicationModal); // 设置全局模态,原窗口不可点击 cp->show(); QEventLoop loop; // 换成Qt5新语法,编译期检查连接正确性 connect(cp, &ClusterPostcoordination::destroyed, &loop, &QEventLoop::quit); loop.exec(); } // 删掉this->show() } catch (exception &e) { qDebug() << e.what(); }
更优实现方案
你的需求是Qt框架的标准模态对话框场景,不需要自己手动实现QEventLoop阻塞逻辑,代码可以简化为:
- 先将
ClusterPostcoordination类的父类从QWidget改为QDialog - 替换逻辑代码为:
try { vector<ICD11> postcoordinations = dbhandler->QueryHasPostcoords(temp,ICD11cluster); if(!postcoordinations.empty()){ // 栈上创建对象,自动管理内存,避免内存泄漏 ClusterPostcoordination cp(this, &temp, &postcoordinations, &ICD11cluster); // 模态执行,阻塞到对话框关闭才返回,父窗口全程不可点击 cp.exec(); } } catch (exception &e) { qDebug() << e.what(); }
该方案完全规避了手动操作窗口显示、手动维护事件循环带来的所有问题,父窗口全程正常显示、关闭子窗口后可以直接正常操作,符合你的预期需求。
内容的提问来源于stack exchange,提问作者SlimLamie
相关产品推荐
相关产品推荐

