QMLの基礎 - QMLとC++のバインディング

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

QMLとC++のバインディング手順を記載する。

ここでは、Qt Creatorにおいて、Qt Quickの空のプロジェクトを作成した時に自動生成されるソースコードを元にする。


QMLからC++へアクセスする (推奨)

setContextPropertyメソッドにQObjectのインスタンスを渡して、QMLからC++のクラスメソッドを呼んでいる。

 // main.cppファイル
 
 #include <QGuiApplication>
 #include <QQmlApplicationEngine>
 #include "CMainWindow.h"
 
 int main(int argc, char *argv[])
 {
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 #endif
 
    QGuiApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
    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);
 
    // 追加
    CMainWindow MainWindow;
    engine.rootContext()->setContextProperty("MainWindow", &MainWindow);
 
    // 複数のクラスを追加する場合、以下のように記述する
    //CSubWindow SubWindow;
    //engine.rootContext()->setContextProperty("SubWindow", &SubWindow);
 
    return app.exec();
 }


 // CMainWindow.hファイル
 
 #pragma once
 
 #include <QObject>
 #include <QString>
 
 class CMainWindow : public QObject
 {
    Q_OBJECT
 
    public:
       Q_INVOKABLE QString getTextFromCpp()
       {
          return QString("This is the text from C++");
       }
 };


 // main.qmlファイル
 
 import QtQuick 2.5
 import QtQuick.Window 2.2
 
 Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
 
    // 追加
    Text {
        id: textMainMessage
        text: qsTr("ここにテキストが表示される")
 
        x: (parent.width / 2) - width / 2
        y: (parent.height / 2) - height / 2
        Layout.fillWidth: true
        Layout.fillHeight: true

        font.pixelSize: 15
        color: "#ffffff"
    }
 
    Button {
        id: mainWindowButton
        x: (parent.width / 2) - width / 2
        y: (parent.height / 2) + height / 2
        width: 120
        height: 35
        Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
        text: qsTr("OK")
 
        Connections {
           target: mainWindowButton
           function onClicked() {
              let strMainMessage = MainWindow.getTextFromCpp();  // C++のメソッドを呼ぶ
              textMainMessage.text = strMainMessage;
           }
        }
    }
 }



C++からQMLオブジェクトへアクセスする (非推奨)

C++からQMLオブジェクトへのアクセスは、C++とQMLの独立性の観点から非推奨であることに注意する。

ここでは、objectNameでアクセスする方法を記載する。(他にも様々な手順がある)

まず、root要素へアクセスして、子要素であるTextへQMLで定義するobjectNameでアクセスする。

 // main.cppファイル
 
 #include <QGuiApplication>
 #include <QQmlApplicationEngine>
 #include "CMainWindow.h"
 
 int main(int argc, char *argv[])
 {
 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 #endif
 
    QGuiApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
    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);
 
    // 追加
    // ルートオブジェクトおよびmain.qmlに定義されているobjectName(textObject)のQMLオブジェクトへのアクセスを取得する
    QObject *rootObject = engine.rootObjects().first();
    QObject *qmlObject = rootObject->findChild<QObject*>("textObject");
 
    // QMLオブジェクトに対して、任意の値を設定する
    qmlObject->setProperty("text", "Text from C++");
 
    return app.exec();
 }


次に、QML側では、アクセスする子要素にobjectNameを定義する。

 // main.qmlファイル
 
 import QtQuick 2.5
 import QtQuick.Window 2.2
 
 Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
 
    // 追加
    Text {
        id: textMainMessage
        objectName: "textObject"
        text: qsTr("ここにテキストが表示される")
 
        x: (parent.width / 2) - width / 2
        y: (parent.height / 2) - height / 2
        Layout.fillWidth: true
        Layout.fillHeight: true

        font.pixelSize: 15
        color: "#ffffff"
    }
 }