You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt Quick 6.8如何打开第二个主窗口且关闭原窗口后不退出应用?

Qt Quick 6.8:主窗口关闭后新窗口自动关闭的解决方案

问题原因

你遇到的新窗口自动关闭,本质是QML垃圾回收机制销毁了新窗口对象:在MainWindow的代码中,newWindow是局部变量,当主窗口关闭后,其所属的QML上下文被销毁,该局部变量被回收,导致对应的窗口对象被销毁,最终新窗口关闭。

另外关于Qt6的默认行为:QGuiApplication默认开启quitOnLastWindowClosed(值为true),只有当最后一个窗口关闭时才会触发应用退出。你的场景里新窗口先关闭,并非应用主动退出,而是对象被回收导致的。

合理实现方式

以下两种方案可解决问题,核心是让新窗口对象的引用脱离主窗口的上下文,避免被垃圾回收:

方案1:用全局单例持有窗口引用

确保单例对象被正确注册,使其生命周期与应用一致,从而持久保存新窗口的引用:

  1. 定义单例QML文件(如WindowStore.qml)
pragma Singleton
import QtQuick 2.15

QtObject {
    property Window secondWindow: null
}
  1. 注册单例
    在CMakeLists.txt中添加单例注册(或在main函数中通过代码注册):
qt_add_qml_module(MainModule
    URI MainModule
    VERSION 1.0
    QML_FILES
        MainWindow.qml
        WindowStore.qml
    SINGLETONS
        WindowStore.qml
)
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:11:20