Qt の C++ から QML の function を実行する方法
QML 内に記述された JavaScript の function を C++ から呼び出してみたいと思ったことはありませんか?ありませんか?
というわけで(以前に試してみてたしかダメだったのですが、Qt 5.2 から JavaScript の実行エンジンが変わったことによって、ひょっとして今ならできるかも?と思って再度)試してみました。
exec-function-in-qml-from-cpp.pro
TEMPLATE = app TARGET = exec-function-in-qml-from-cpp QT = qml SOURCES = main.cpp RESOURCES = main.qrc
シンプルなコンソールアプリで QML の実験をするための最小構成になっています。
main.qml
import QtQml 2.2
QtObject {
id: root
function echo(msg) {
console.debug(msg)
return msg
}
}
これが今回使用する QML ファイルで、この echo 関数を C++ から実行します。
main.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
QML ファイルをリソースに埋め込みます。
main.cpp
#include <QtQml>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(QUrl("qrc:/main.qml"));
QObject *object = component.create();
{
const QMetaObject *metaObject = object->metaObject();
for (int i = object->staticMetaObject.methodCount(); i < metaObject->methodCount(); i++) {
qDebug() << i << metaObject->method(i).name();
QVariant ret;
qDebug() << metaObject->method(i).invoke(object, Qt::DirectConnection, Q_RETURN_ARG(QVariant, ret), Q_ARG(QVariant, QStringLiteral("test")));
qDebug() << ret;
}
}
delete object;
QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
return app.exec();
}
QQmlEngine を使用して main.qml を実行します。
作成した main.qml のオブジェクトのメタオブジェクトから main.qml 内で作成された function を取得し、実行結果をデバッグ出力しています。
実行
$ qmake $ make $ ./exec-function-in-qml-from-cpp 5 "echo" qml: test true QVariant(QString, "test")
というわけで、C++ から QML で定義した関数を呼べることがわかりました。QVariant で返値と引数を渡してあげるのがポイントですね。