QML にグローバル関数を追加する方法

はじめに

QML や QML で利用される JavaScript にグローバル関数を追加したいことがたまに(たまに)ありますね。

やりかた

QQmlEnginerootContextcontextObject を設定してあげることで、その QObject が提供しているスロットや Q_INVOKABLE がつけられたメソッドを QML から実行することができます。

プロジェクトファイル

QT = qml
SOURCES = main.cpp
RESOURCES = qml.qrc

main.cpp

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>

class GlobalContext : public QObject
{
    Q_OBJECT
public:
    explicit GlobalContext(QObject *parent) : QObject(parent) {}
    Q_INVOKABLE void MyFunction(const QString &arg) {
        qInfo() << Q_FUNC_INFO << arg;
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextObject(new GlobalContext(&app));
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

#include "main.moc"

main.qml

import QtQml 2.15
import 'main.js' as Script

QtObject {
    Component.onCompleted: {
        MyFunction('from QML')
        Script.run()
        Qt.quit()
    }
}

main.js

function run() {
    MyFunction('from JavaScript')
}

qml.qrc

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
        <file>main.js</file>
    </qresource>
</RCC>

実行結果

void GlobalContext::MyFunction(const QString&) "from QML"
void GlobalContext::MyFunction(const QString&) "from JavaScript"

説明

やりかたに書いたとおり main.cpp の適切な場所で、以下のとおりコンテキストオブジェクトを設定しています。

engine.rootContext()->setContextObject(new GlobalContext(&app));

これにより、GlobalContext が提供している Q_INVOKABLE がついたメソッドが QML からも JavaScript からもグローバルに呼び出せるようになっています。

おわりに

便利ですが、やりすぎないように注意しましょう!

おすすめ