MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
QMLの基礎 - QMLとC++のバインディングのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
QMLの基礎 - QMLとC++のバインディング
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == QMLとC++のバインディング手順を記載する。<br> <br> ここでは、Qt Creatorにおいて、Qt Quickの空のプロジェクトを作成した時に自動生成されるソースコードを元にする。<br> <br><br> == QMLからC++へアクセスする (推奨) == <code>setContextProperty</code>メソッドに<code>QObject</code>のインスタンスを渡して、QMLからC++のクラスメソッドを呼んでいる。<br> <syntaxhighlight lang="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(); } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // 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++"); } }; </syntaxhighlight> <br> <syntaxhighlight lang="qml"> // 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; } } } } </syntaxhighlight> <br><br> == C++からQMLオブジェクトへアクセスする (非推奨) == <u>C++からQMLオブジェクトへのアクセスは、C++とQMLの独立性の観点から非推奨であることに注意する。</u><br> <br> ここでは、objectNameでアクセスする方法を記載する。(他にも様々な手順がある)<br> <br> まず、root要素へアクセスして、子要素である<code>Text</code>へQMLで定義する<code>objectName</code>でアクセスする。<br> <syntaxhighlight lang="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); // 追加 // ルートオブジェクトおよび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(); } </syntaxhighlight> <br> 次に、QML側では、アクセスする子要素に<code>objectName</code>を定義する。<br> <syntaxhighlight lang="qml"> // 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" } } </syntaxhighlight> <br><br> == シグナルとスロット == 以下の例では、QML側のボタン押下時にC++側へシグナルを出力してC++側のスロットで受信した後、C++側からQML側へシグナルを送出している。<br> <br> ==== C++側でコネクトする ==== <u>C++側からのシグナルにおいて、引数を<code>QVariant</code>にする必要がある。</u><br> これを指定しない場合、QML側のスロットが認識されない。<br> <syntaxhighlight lang="qml"> // main.qmlファイル import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Controls 2.0 Window { signal qmlSignal(string msg); function qmlSlot(text) { console.log("qmlSlot is called with the text: " + text) textField.text = text; } visible: true width: 640 height: 480 title: qsTr("Hello World") Text { id:textField text: qsTr("Hello World") anchors.centerIn: parent } Button { id:aButton text:"Emit Signal!" anchors.centerIn: parent anchors.verticalCenterOffset: 30 onClicked: qmlSignal("Hello from QML") } } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "CSignalSlot.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); CSignalSlot SignalSlot; QObject *root = engine.rootObjects().first(); // Connect QML Signal to C++ Slot QObject::connect(root, SIGNAL(qmlSignal(QString)), &SignalSlot, SLOT(cppSlot(QString))); // Connect C++ Signal to QML Slot QObject::connect(&SignalSlot, SIGNAL(cppSignal(QVariant)), root, SLOT(qmlSlot(QVariant))); return app.exec(); } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // CSignalSlot.hファイル #ifndef CSIGNALSLOT_H #define CSIGNALSLOT_H #include <QObject> #include <QVariant> #include <QDebug> class CSignalSlot : public QObject { Q_OBJECT public: explicit CSignalSlot(QObject *parent = 0) : QObject(parent) { } signals: void cppSignal(QVariant text); public slots: void cppSlot(QString msg) { qDebug() << "cppSlot is called with the message: " << msg; emit cppSignal("Hello from C++"); } }; #endif // CSIGNALSLOT_H </syntaxhighlight> <br> ==== QML側でコネクトする ==== C++側からシグナル(cppSignalメソッド)を送出する時の動作をonCppSignalと記述する。<br> <u>これは、C++側はLower Camelで記述、QML側は"on" + Upper Camelで記述する必要がある。</u><br> <br> main.cppにおいて、ルートオブジェクト(<code>rootContext</code>クラス)のコンテキスト(<code>setContextProperty</code>メソッド)を設定する前にmain.qmlを読み込むと、<br> 以下のエラーが出力されるため注意すること。<br> QML Connections: Cannot assign to non-existent property "OnCppSignal" ReferenceError: cppSignalSlot is not defined <br> <syntaxhighlight lang="qml"> // main.qmlファイル import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Controls 2.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Text { id: textField text: qsTr("Hello World") anchors.centerIn: parent } Button { text:"Emit Signal!" anchors.centerIn: parent anchors.verticalCenterOffset: 30 onClicked: cSignalSlot.cppSlot("Hello from QML") } Connections { target:cSignalSlot onCppSignal: { console.log("received cppSignal:" + text) textField.text = text; } } } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "CSignalSlot.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; CSignalSlot SignalSlot; // Put this before lading qml file! engine.rootContext()->setContextProperty("CSignalSlot", &SignalSlot); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // CSignalSlot.hファイル #ifndef CSIGNALSLOT_H #define CSIGNALSLOT_H #include <QObject> #include <QDebug> class CSignalSlot : public QObject { Q_OBJECT public: explicit CSignalSlot(QObject *parent = 0) : QObject(parent) { } signals: void cppSignal(QString text); public slots: void cppSlot(QString text) { qDebug() << "cppSlot is called with text: " + text; emit cppSignal(QString("Hello from C++")); } }; #endif // CSIGNALSLOT_H </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
QMLの基礎 - QMLとC++のバインディング
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse