簡體   English   中英

如何為 qmlRegisterSingletonType 實現單例提供程序?

[英]How to implement a singleton provider for qmlRegisterSingletonType?

我想在 QML 中使用 C++ 類作為單例實例,並認為我必須使用 qmlRegisterSingletonType 注冊它們。 此函數需要一個函數,該函數提供已注冊 C++ 類的實例。 我在 Windows 上使用包含 MinGW 4.8 的最新 Qt 5.3.1。

文檔顯示了以下提供程序函數的示例:

static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine, 
    QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)

    static int seedValue = 5;
    QJSValue example = scriptEngine->newObject();
    example.setProperty("someProperty", seedValue++);
    return example;
}

我嘗試使用它,但是當我在頭文件的類范圍之外定義這樣一個函數時,我收到編譯器警告,發生在另一個包含相同頭文件的 cpp 文件中:

warning: 'QObject* example_qjsvalue_singletontype_provider(QQmlEngine*, 
QJSEngine*)' defined but not used [-Wunused-function]

此外,編寫一個從不同的 cpp 文件調用時返回一個新實例的單例提供程序感覺是錯誤的。 所以我嘗試了一個自己的實現,我使用靜態類成員來返回實例:

// mysingleton.h
class MySingleton: public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(MySingleton)
public:
    static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine) {

        Q_UNUSED(engine)
        Q_UNUSED(scriptEngine)

        if(!m_instance)
        {
            m_instance = new MySingleton();
        }
        return m_instance;
    }
    MySingleton(QObject* parent = 0)
        :QObject(parent)
    {}
private:
    static QObject* m_instance;
};

我嘗試使用...

qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton", 
MySingleton::qmlInstance);

此解決方案也不起作用,我收到鏈接器錯誤:

release/main.o:main.cpp:
(.text$_ZN11MySingleton11qmlInstanceEP10QQmlEngineP9QJSEngine[__ZN11MySingleton11
qmlInstanceEP10QQmlEngineP9QJSEngine]+0x42): undefined reference to 
`MySingleton::m_instance'

提供所需的單例實例 1) 具有類范圍之外的函數和 2) 具有類成員函數的正確解決方案是什么?

為什么該示例建議在每次調用提供程序函數時創建一個新實例?

編寫一個單獨的提供程序,從不同的cpp文件調用時返回一個新實例,這是錯誤的。 所以我嘗試了一個自己的實現,我使用靜態類成員來返回實例

從文檔引用到qmlRegisterSingletonType函數:

注意:從單一類型提供程序返回的QObject單例類型實例由QML引擎擁有。 出於這個原因,單類型提供的功能應該被實現為一個單獨的工廠。

這意味着當單例類型提供程序返回一個新實例時,這種行為是通過意圖完成的,盡管事實上它正如你所指出的那樣,乍一看看起來很奇怪。 所以,你的類實現應該如下所示:

class MySingleton: public QObject
{
    Q_OBJECT
    Q_DISABLE_COPY(MySingleton)

    MySingleton() {}

public:
    static QObject *qmlInstance(QQmlEngine *engine, QJSEngine *scriptEngine)
    {
        Q_UNUSED(engine);
        Q_UNUSED(scriptEngine);

        return new MySingleton;
    }
};

此外,您應該為MySingleton::qmlInstance使用&符號,因為它是一個成員方法。 有關詳細信息,請參閱 然后注冊看起來應該如此:

qmlRegisterSingletonType<MySingleton>(uri, 1, 0, "MySingleton", &MySingleton::qmlInstance);

問題是(您的第二個示例)您必須初始化m_instance靜態成員變量。 您可以在mysingleton.cpp文件中執行此操作,例如:

QObject * MySingleton::m_instance = 0;

在 Qt 5.6 中, qmlRegisterSingletonType文檔中的qmlRegisterSingletonType已更新:

注意:從單例類型提供程序返回的 QObject 單例類型實例歸 QML 引擎所有,除非該對象明確設置了 QQmlEngine::CppOwnership 標志。

因此,您可以完全控制單例實例的創建方式。 這是一個使用Q_GLOBAL_STATIC的示例:

Q_GLOBAL_STATIC(MySingleton, singletonInstance)

MySingleton::MySingleton(QObject *parent) :
    QObject(parent)
{
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}

Clipboard *MySingleton::instance()
{
    return singletonInstance();
}

QObject *MySingleton::qmlInstance(QQmlEngine *, QJSEngine *)
{
    return MySingleton::instance();
}

如果你想從c ++調用這個單例類,請更改該行

return new MySingleton;

至:

return new &MySingleton;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM