简体   繁体   English

qmlRegisterSingletonType和多个顶级窗口

[英]qmlRegisterSingletonType and multiple top-level windows

I have a QGuiAppplication derived class (called Sy_application ) that I've wrapped with another (called Sy_application_qml , with extra some QML specific features) and then registered that as a singleton with the QML engine. 我有一个QGuiAppplication派生类(称为Sy_application ),该类已经包装了另一个类(称为Sy_application_qml ,具有其他一些QML特定功能),然后将其注册为QML引擎的单例。

This all works fine from the first opened top-level window, but the second (and presumably any more) only gets null from the singleton. 所有这些都可以从第一个打开的顶级窗口正常运行,但是第二个(可能还有更多)仅从单例中获取null Adding some debug: 添加一些调试:

// 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();
}

And the debug output: 和调试输出:

// Opening first window.
Creating

// Creating second
qml: Sy_application_qml(0x1895b30)
Getting: Sy_application(0x7fff80f051c0)

// Attempting to create third
qml: Sy_application_qml(0x1895b30)
Getting: Sy_application(0x7fff80f051c0)
qrc:/qml/gui/dialogs/Sy_newProjectDialog.qml:62: TypeError: Cannot call method 'newProject' of null

As you can see the singleton is still present and the C++ Sy_application instance is being returned correctly, but is appearing as null on the QML side. 如您所见,单例仍然存在,并且C ++ Sy_application实例已正确返回,但在QML端显示为null Any reason why it works for one window and not another? 它对一个窗口而不对另一个窗口起作用的任何原因是什么?

So I finally worked it out, and it had nothing to do with QML singletons or having multiple top-level windows - but it had everything to do with passing QObject pointers to the QML engine from Q_INVOKABLE methods (the Sy_application_qml::get() method in my case). 所以我终于解决了这个问题,它与QML单例无关,也没有多个顶层窗口-但这与从Q_INVOKABLE方法( Sy_application_qml::get()方法Sy_application_qml::get()传递QObject指针到QML引擎有关。就我而言)。

From the docs: 从文档:

Objects not-created by QML have CppOwnership by default. 默认情况下,不是由QML创建的对象具有CppOwnership。 The exception to this is objects returned from C++ method calls; 从C ++方法调用返回的对象是一个例外。 in these cases, the ownership of the returned objects will be set to JavaScriptOwnerShip. 在这些情况下,返回对象的所有权将设置为JavaScriptOwnerShip。 Note this applies only to explicit invocations of Q_INVOKABLE methods or slots, and not to property getter invocations. 请注意,这仅适用于Q_INVOKABLE方法或插槽的显式调用,不适用于属性getter调用。

So the QML engine had deleted my Sy_application pointer. 因此,QML引擎删除了我的Sy_application指针。 The solution was nice and simple: 解决方案非常简单:

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM