【问题标题】:How to find out the QQmlEngine instance of a singleton object?如何找出单例对象的 QQmlEngine 实例?
【发布时间】:2018-06-22 23:01:21
【问题描述】:

我有一个类SingletonBaseClass,它在 C++ 中定义,后来在 QML 中扩展。在 qmldir 文件中,它被标记为 Singleton:

// qmldir file
singleton SingletonClass 1.0 SingletonClass.qml

// SingletonClass.qml
import QtQml 2.0
pragma Singleton
SingletonBaseClass {
    // ...
}

这是基类:

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

    // Get the owner engine
    Q_INVOKABLE void someMethodCalledFromQml()
    {
        QQmlEngine* ownerEngine = ?
    }

    // Get the single instance of the given engine
    static SingletonBaseClass* instance(QQmlEngine* engine)
    {
        SingletonBaseClass* instance = ?
        return instance;
    } 

};
  1. 如何在 SingletonBaseClass 中检索 QQmlEngine 实例?
  2. 如何从静态函数中获取指向我的单例实例的指针?

注意:我的应用程序中有多个 QML 引擎实例。

[更新]:我对建议的解决方法不满意,因此我最终为 1. 和QQmlEngine::singletonInstance() 贡献了 this patch 为 2。这两个更改都将在 Qt 5.12 中可用。

【问题讨论】:

  • 你想用 C++ 还是 QML 获得 QQmlEngine?
  • 如果你使用qmlRegisterSingletonType注册你的单例,那么指向QQmlEngine的指针就是callback function参数之一
  • 我明确写过单例是在 QML 中实例化的,因此没有单例提供者回调。

标签: qt qml qqmlengine


【解决方案1】:

如果您想获得QQmlEngine,可以使用contextForObject() 方法,如下所示:

Q_INVOKABLE void someMethodCalledFromQml()
{
    QQmlEngine *ownerEngine = QQmlEngine::contextForObject(this)->engine();
    qDebug()<<ownerEngine;
}

qml 中的单例没有父对象,因此访问它们的方法是创建一个属性,为此我们创建一个 .qml 并使用该属性创建一个对象作为单例:

qrc:/tmp.qml

import QtQuick 2.0

QtObject {
    property var obj: SingletonClass
}

然后通过以下代码访问该元素:

static SingletonBaseClass* instance(QQmlEngine* engine)
{
    QQmlComponent component(engine, QUrl("qrc:/tmp.qml"));
    QObject *item = component.create();
    SingletonBaseClass *instance = qvariant_cast<SingletonBaseClass *>(item->property("obj"));
    return instance;
}

在下面的link我们展示一个例子。

【讨论】:

  • 感谢您抽出宝贵的时间和广泛的回答。第一部分,the documentation says contextForObject() 应该为单例类型返回 NULL。你知道为什么它在这种情况下仍然有效吗?也许是因为它被实例化为 QML 组件而不使用单例提供程序函数?第二部分:好把戏!我试图通过将内容放入 QQmlExpression 来避免附加文件,但这不起作用。可能是因为QTBUG-33514
  • 从您的链接中,我没有看到 contextForObject() 为单例类型返回 NULL。如果单例由 QML 实例化,则它拥有单例。但是,C++ 代码可以在 QML 引用之前实例化单例。也许在 C++ 中实例化的具有 C++ 所有权的单例将返回 nullptr,因为它的所有者不是 QML。附带说明,如果在 C++ 中实例化,请调用 QQmlEngine::setObjectOwnership() 以防止 QML 删除它,否则您的应用程序将间歇性崩溃。一旦在 QML 中被引用,QML 就会获得所有权,并会在运行时在适当的情况下将其删除。
猜你喜欢
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 2014-03-01
相关资源
最近更新 更多