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

如何在QML中动态创建Qt Widget?QMainWindow创建后闪退问题

解决方案:QML中动态创建带参数的自定义QMainWindow

问题分析

你第二种方法中窗口显示后立即消失并退出程序的核心原因是:QML引擎默认会接管C++返回对象的所有权,当创建窗口的JS代码执行完毕后,若没有QML变量持有该窗口引用,QML的垃圾回收机制会销毁这个窗口对象;而如果该窗口是当前唯一的顶层窗口,Qt应用会因无活跃顶层窗口而退出。

正确实现步骤

1. 修正MainWindowFactory类

在工厂类的创建方法中,显式将窗口的所有权交给C++端管理,避免QML引擎自动销毁它:

#include <QObject>
#include <QQmlEngine>
#include "MainWindow.h"

class MainWindowFactory : public QObject
{
    Q_OBJECT
public:
    explicit MainWindowFactory(QObject *parent = nullptr) : QObject(parent) {}

    // 暴露可被QML调用的创建方法,支持传递参数
    Q_INVOKABLE MainWindow* createMainWindow(int gameType) {
        MainWindow* mainWindow = new MainWindow(static_cast<GameType>(gameType));
        mainWindow->setAttribute(Qt::WA_DeleteOnClose);
        // 关键:设置对象所有权为C++端,防止QML自动回收
        QQmlEngine::setObjectOwnership(mainWindow, QQmlEngine::CppOwnership);
        return mainWindow;
    }
};

2. 正确注册工厂类

注意注册时的类型名称不要和你的MainWindow类混淆(之前你用了"MainWindow"作为单例名称,容易冲突):

qmlRegisterSingletonType<MainWindowFactory>(
    "Kmc", 1, 0, "MainWindowFactory",
    [](QQmlEngine*, QJSEngine*) -> QObject* { return new MainWindowFactory(); });

3. QML中调用工厂创建窗口

在QML的按钮点击事件中,调用工厂方法并持有窗口引用(或直接调用show):

import QtQuick.Controls 2.15
import Kmc 1.0

Button {
    text: "打开PVE窗口"
    onClicked: {
        // 0对应GameType::PVE,若要使用枚举名称需额外注册
        let mainWin = MainWindowFactory.createMainWindow(0)
        mainWin.show()
    }
}

4. 可选:注册GameType枚举到QML

如果想在QML中直接使用GameType.PVE而非数值,需提前注册枚举类型:

#include <QMetaEnum>

// 在main函数中注册枚举
qRegisterMetaType<GameType>("GameType");
qmlRegisterUncreatableMetaObject(
    GameType::staticMetaObject,
    "Kmc", 1, 0,
    "GameType",
    "Cannot instantiate GameType enum"
);

之后QML中即可这样调用:

let mainWin = MainWindowFactory.createMainWindow(GameType.PVE)

补充说明

  • 第一种方法(普通单例函数)无法传递构造参数是因为单例的创建逻辑固定,工厂模式是更适合动态创建带参数对象的方案。
  • 设置Qt::WA_DeleteOnClose后,窗口关闭时会自动销毁自身,无需手动管理内存。

内容的提问来源于stack exchange,提问作者Kamichanw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:00:19