QML にグローバル関数を追加する方法
はじめに
QML や QML で利用される JavaScript にグローバル関数を追加したいことがたまに(たまに)ありますね。
やりかた
QQmlEngine の rootContext に contextObject を設定してあげることで、その QObject が提供しているスロットや Q_INVOKABLE がつけられたメソッドを QML から実行することができます。
プロジェクトファイル
QT = qml
SOURCES = main.cpp
RESOURCES = qml.qrc
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"
#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
main.js
function run() {
MyFunction('from JavaScript')
}
MyFunction('from JavaScript')
}
qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>main.js</file>
</qresource>
</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 からもグローバルに呼び出せるようになっています。
おわりに
便利ですが、やりすぎないように注意しましょう!