Qt qmlRegisterSingletonType和多个顶级窗口

Qt qmlRegisterSingletonType和多个顶级窗口,qt,qml,Qt,Qml,我有一个名为Sy_application的qguiapplication派生类,我用另一个名为Sy_application_qml的类包装了它,它具有一些额外的qml特定特性,然后将其注册为qml引擎的单例 从第一个打开的顶级窗口开始,这一切都可以正常工作,但是第二个窗口(可能还有更多的窗口)只从单例窗口获得null。添加一些调试: // The static factory method used in the qmlRegisterSingletonType call. QObject* S

我有一个名为Sy_application的qguiapplication派生类,我用另一个名为Sy_application_qml的类包装了它,它具有一些额外的qml特定特性,然后将其注册为qml引擎的单例

从第一个打开的顶级窗口开始,这一切都可以正常工作,但是第二个窗口(可能还有更多的窗口)只从单例窗口获得null。添加一些调试:

// The static factory method used in the qmlRegisterSingletonType call.
QObject* Sy_application_qml::factory( QQmlEngine* engine,
                                      QJSEngine* scriptEngine )
{
    Q_UNUSED( engine )
    Q_UNUSED( scriptEngine )

    qDebug() << "Creating";
    return new Sy_application_qml();
}

// SY_APP is the qApp macro casted to my Sy_application type.
QObject* Sy_application_qml::get()
{
    qDebug() << "Getting:" << SY_APP;
    return SY_APP;
}

// This is an example of it's use within QML
onPositiveClicked: {
    console.log( Sy_application_qml );
    Sy_application_qml.get().newProject( sampleRate.value, frameRate.value );
    close();
}

正如您所看到的,单体仍然存在,C++ Syl应用程序实例被正确返回,但在QML侧出现为空。为什么它只适用于一个窗口而不适用于另一个窗口?

所以我最终解决了这个问题,它与QML单例或具有多个顶级窗口无关,但它与将QObject指针从Q_可调用方法传递到QML引擎有关,在我的例子中是Sy_应用程序的QML::get方法

从文档中:

默认情况下,非QML创建的对象具有CPP所有权。例外 这是从C++方法调用返回的对象;在这些情况下 返回对象的所有权将设置为JavaScriptOwner。 注意,这只适用于Q_可调用方法的显式调用 或插槽,而不是属性getter调用

因此QML引擎删除了我的Sy_应用程序指针。解决方案非常简单:

QObject* Sy_application_qml::factory( QQmlEngine* engine,
                                      QJSEngine* scriptEngine )
{
    Q_UNUSED( engine )
    Q_UNUSED( scriptEngine )

    QQmlEngine::setObjectOwnership( SY_APP, QQmlEngine::CppOwnership );
    return new Sy_application_qml();
}

From doc:为了在QML中使用已注册的单例类型,必须导入单例类型。你在这么做吗?另外,真的,你有没有尝试另外注册Sy_应用程序?看起来qmlRegisterSingletonType没有注册您的自定义项type@N1ghtLight是的,我正在导入它,否则QML将无法编译。我不需要注册Sy_应用程序,因为我不想在QML中创建它的任何实例;由于QML引擎最终源于QObject,因此它可以在没有注册的情况下读取其属性,这也是它第一次工作的原因。事实上,如果我将它注册为singleton类型,那么在启动第一个窗口时会创建另一个Sy_应用程序,这将非常糟糕。。。这个问题的可编译示例将是greatIt,这没有什么区别,因为我不想从QML实例化另一个实例。您不需要注册QObject派生类型来访问它的属性,如果不是这种情况,它第一次就不会工作。我的可编译示例运行良好,因此还有其他一些问题。。。
QObject* Sy_application_qml::factory( QQmlEngine* engine,
                                      QJSEngine* scriptEngine )
{
    Q_UNUSED( engine )
    Q_UNUSED( scriptEngine )

    QQmlEngine::setObjectOwnership( SY_APP, QQmlEngine::CppOwnership );
    return new Sy_application_qml();
}