Qt Quick 6.8如何打开第二个主窗口且关闭原窗口后不退出应用?
Qt Quick 6.8:主窗口关闭后新窗口自动关闭的解决方案
问题原因
你遇到的新窗口自动关闭,本质是QML垃圾回收机制销毁了新窗口对象:在MainWindow的代码中,newWindow是局部变量,当主窗口关闭后,其所属的QML上下文被销毁,该局部变量被回收,导致对应的窗口对象被销毁,最终新窗口关闭。
另外关于Qt6的默认行为:QGuiApplication默认开启quitOnLastWindowClosed(值为true),只有当最后一个窗口关闭时才会触发应用退出。你的场景里新窗口先关闭,并非应用主动退出,而是对象被回收导致的。
合理实现方式
以下两种方案可解决问题,核心是让新窗口对象的引用脱离主窗口的上下文,避免被垃圾回收:
方案1:用全局单例持有窗口引用
确保单例对象被正确注册,使其生命周期与应用一致,从而持久保存新窗口的引用:
- 定义单例QML文件(如
WindowStore.qml)
pragma Singleton import QtQuick 2.15 QtObject { property Window secondWindow: null }
- 注册单例
在CMakeLists.txt中添加单例注册(或在main函数中通过代码注册):
qt_add_qml_module(MainModule URI MainModule VERSION 1.0 QML_FILES MainWindow.qml WindowStore.qml SINGLETONS WindowStore.qml )
- 修改MainWindow中的窗口创建代码
import QtQuick.Window 2.15 import MainModule 1.0 ApplicationWindow { id: mainWindow function openSecondWindow() { let component = Qt.createComponent("../../BoxModule/BoxWindow.qml") // 监听组件加载状态,避免异步加载问题 component.statusChanged.connect(() => { if (component.status === Component.Ready) { // 父对象设为null,让新窗口成为独立窗口 let newWindow = component.createObject(null) newWindow.showMaximized() // 将窗口引用存入单例,避免被回收 WindowStore.secondWindow = newWindow mainWindow.close() } }) } }
方案2:在C++层创建并持有新窗口
通过C代码创建新窗口,利用C的对象生命周期管理避免QML垃圾回收的影响:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQuickWindow> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 保持默认的"最后一个窗口关闭时退出"行为 app.setQuitOnLastWindowClosed(true); QQmlApplicationEngine engine; const QUrl mainWindowUrl(u"qrc:/MainModule/MainWindow.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [&engine](QObject *obj, const QUrl &objUrl) { if (obj && objUrl.toString().contains("MainWindow")) { QQuickWindow *mainWindow = qobject_cast<QQuickWindow*>(obj); // 监听主窗口关闭事件 QObject::connect(mainWindow, &QQuickWindow::closing, [&engine]() { QQmlComponent secondWindowComponent(&engine, QUrl(u"qrc:/BoxModule/BoxWindow.qml"_qs)); if (secondWindowComponent.isReady()) { // 创建窗口,C++层持有指针,避免被QML回收 QQuickWindow *newWindow = qobject_cast<QQuickWindow*>( secondWindowComponent.create()); if (newWindow) { newWindow->showMaximized(); } } }); } }, Qt::QueuedConnection); engine.load(mainWindowUrl); return app.exec(); }
关于Qt6中窗口关闭与应用退出的说明
Qt6默认情况下,QGuiApplication::quitOnLastWindowClosed为true,即只有当所有窗口都关闭时,应用才会自动退出。如果关闭的不是最后一个窗口,应用不会退出。你之前的场景中,新窗口关闭是因为对象被垃圾回收,并非应用主动退出。
内容的提问来源于stack exchange,提问作者Brannon
相关产品推荐
相关产品推荐

