Qt Quick Android Studioプロジェクト向け

Qt Quick Android向けAPIのサンプルはAndroid Studioプロジェクトとして提供されています
Qt Quick for Android の API サンプルは、Android Studio プロジェクトとして提供されています。プロジェクトフォルダは、Qt のインストール先にあります。
たとえば、Windows のデフォルトのインストールパスでは、以下の場所に配置されています:
C:\Qt\Examples\Qt-<patch-release-number>\platforms\android\<example-name>これらのプロジェクトは、この Qt バージョンと互換性のあるQt Gradle プラグインのバージョンを使用するよう、すでに設定されています。
概要
このサンプルには、Qt Tools for Android Studioプラグインを使用してAndroid StudioにインポートできるQmlプロジェクトが含まれています。また、QtQuickViewAPIを利用して、このQmlプロジェクトをビューとして使用するJavaおよびKotlinプロジェクトも含まれています。
QMLの仕組みに関する詳細については、 Qt Qmlを参照してください。このドキュメントでは、Java または Kotlin を使用して QML コンポーネントを Android アプリケーションに組み込む方法に焦点を当てています。
Qt Quick for Android API では、main() への変更が必要となります。
一般的なQt Quick アプリケーションのmain.cppは、次のような構成になっています:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreationFailed,
&app,
[]() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
engine.loadFromModule("MyQtQuickProject", "Main");
return app.exec();
}main() では、QMLエンジンを作成したり、後でQt Quick のView APIによって処理されるQMLをロードしたりする必要はありません。main() に必要なのは、以下のコードだけです:
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
return app.exec();
}レイアウトの設定
JavaプロジェクトとKotlinプロジェクトのいずれにおいても、app/src/main/res/layout/activity_main.xml 内でQtQuickViewのレイアウトを設定する必要があります。
LinearLayout 内で、各QtQuickView に対して 2 つの FrameLayout を設定します。
<FrameLayout
android:id="@+id/firstQmlFrame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
<FrameLayout
android:id="@+id/secondQmlFrame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>この `id ` は、Kotlin または Java で記述された `MainActivity` から参照されるものです。
自動生成されたQML型のJavaクラスのインポート
QML型に対応するJavaクラスは、Qt Quick プロジェクトのビルド時に生成されます。MainActivityでこれらを使用するには、事前にインポートする必要があります。
import org.qtproject.example.qtquickview.QmlModule.Main;
import org.qtproject.example.qtquickview.QmlModule.Second;import org.qtproject.example.qtquickview.QmlModule.Main
import org.qtproject.example.qtquickview.QmlModule.Second注: QMLコンポーネントのJavaコード生成に関する詳細については、CMake変数「QT_ANDROID_GENERATE_JAVA_QTQUICKVIEW_CONTENTS」を参照してください 。
MainActivityのonCreate()メソッド
まず、JavaおよびKotlinプロジェクトのMainActivity のonCreate()メソッドについて見ていきます。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_qmlViewBackgroundText = findViewById(R.id.qmlViewBackgroundText);
m_qmlStatus = findViewById(R.id.qmlStatusText);
m_androidControlsLayout = findViewById(R.id.javaRelative);
m_colorBox = findViewById(R.id.qmlColorBox);
m_switch = findViewById(R.id.disconnectQmlListenerSwitch);
m_switch.setOnClickListener(view -> switchListener());
QtQuickView m_firstQuickView = new QtQuickView(this);
QtQuickView m_secondQuickView = new QtQuickView(this);
// Set status change listener for m_qmlView
// listener implemented below in OnStatusChanged
m_firstQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);
final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout m_firstQmlFrameLayout = findViewById(R.id.firstQmlFrame);
m_firstQmlFrameLayout.addView(m_firstQuickView, params);
FrameLayout m_secondQmlFrameLayout = findViewById(R.id.secondQmlFrame);
m_secondQmlFrameLayout.addView(m_secondQuickView, params);
m_firstQuickView.loadContent(m_firstQmlContent);
m_secondQuickView.loadContent(m_secondQmlContent);
Button m_changeColorButton = findViewById(R.id.changeQmlColorButton);
m_changeColorButton.setOnClickListener(view -> onClickListener());
Button m_rotateQmlGridButton = findViewById(R.id.rotateQmlGridButton);
m_rotateQmlGridButton.setOnClickListener(view -> rotateQmlGrid());
}override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
m_binding = ActivityMainBinding.inflate(layoutInflater)
val view = m_binding.root
setContentView(view)
m_binding.disconnectQmlListenerSwitch.setOnCheckedChangeListener { button, checked ->
switchListener(
button,
checked
)
}
val firstQtQuickView = QtQuickView(this)
val secondQtQuickView = QtQuickView(this)
// Set status change listener for m_qmlView
// listener implemented below in OnStatusChanged
m_firstQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)
val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
m_binding.firstQmlFrame.addView(firstQtQuickView, params)
m_binding.secondQmlFrame.addView(secondQtQuickView, params)
firstQtQuickView.loadContent(m_firstQmlContent)
secondQtQuickView.loadContent(m_secondQmlContent)
m_binding.changeQmlColorButton.setOnClickListener { onClickListener() }
m_binding.rotateQmlGridButton.setOnClickListener { rotateQmlGrid() }
}注: Kotlinプロジェクトでは 、アプリケーションのUIコンポーネントにアクセスするためにViewバインディングを使用しています:
m_binding = ActivityMainBinding.inflate(layoutInflater)
val view = m_binding.root
setContentView(view)onCreate() メソッド内では、以前に宣言された変数が新しいQtQuickViewインスタンスで初期化されます。これらのインスタンスは、Java/KotlinのActivityのContext を引数として受け取ります。
QtQuickView m_firstQuickView = new QtQuickView(this);
QtQuickView m_secondQuickView = new QtQuickView(this);val firstQtQuickView = QtQuickView(this)
val secondQtQuickView = QtQuickView(this)QtQuickViewのインスタンスは、適切なレイアウトパラメータとともにAndroidのレイアウトに追加されます。
final ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout m_firstQmlFrameLayout = findViewById(R.id.firstQmlFrame);
m_firstQmlFrameLayout.addView(m_firstQuickView, params);
FrameLayout m_secondQmlFrameLayout = findViewById(R.id.secondQmlFrame);
m_secondQmlFrameLayout.addView(m_secondQuickView, params);val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
m_binding.firstQmlFrame.addView(firstQtQuickView, params)
m_binding.secondQmlFrame.addView(secondQtQuickView, params)Main およびSecond の Java クラスは、QtQuickViewContentクラスを継承しています。これらのクラスは、インポートした QML プロジェクトから生成されたものです。
private final Main m_firstQmlContent = new Main();
private final Second m_secondQmlContent = new Second();private val m_firstQmlContent: Main = Main()
private val m_secondQmlContent: Second = Second()Qt Quick のコンテンツは、QtQuickView.loadContent() メソッドを通じて読み込まれます。このメソッドは、引数としてQtQuickViewContentを受け取ります。
m_firstQuickView.loadContent(m_firstQmlContent);
m_secondQuickView.loadContent(m_secondQmlContent);firstQtQuickView.loadContent(m_firstQmlContent)
secondQtQuickView.loadContent(m_secondQmlContent)QMLコンポーネントとの連携
組み込まれたQMLコンポーネントとやり取りを行うには、QtQmlStatusChangeListenerインターフェースを実装し、onStatusChanged メソッドをオーバーライドして、QtQuickViewに現在読み込まれているQtQuickViewContentの読み込みステータスを取得します。
public class MainActivity extends AppCompatActivity implements
QtQmlStatusChangeListener {
...
}class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener {
...
}onStatusChanged の実装:
@Override
public void onStatusChanged(QtQmlStatus qtQmlStatus, QtQuickViewContent content) {
Log.i(TAG, "Status of QtQuickView: " + qtQmlStatus);
// Show current QML View status in a textview
m_qmlStatus.setText(getString(R.string.qml_view_status, m_statusNames.get(qtQmlStatus)));
updateColorDisplay();
if (content == m_firstQmlContent) {
// Connect signal listener to "onClicked" signal from main.qml
// addSignalListener returns int which can be used later to identify the listener
if (qtQmlStatus == QtQmlStatus.READY && m_switch.isChecked()) {
m_qmlButtonSignalListenerId = m_firstQmlContent.connectOnClickedListener(
(String name, Void v) -> {
Log.i(TAG, "QML button clicked");
m_androidControlsLayout.setBackgroundColor(Color.parseColor(
m_colors.getColor()
));
});
}
}
}override fun onStatusChanged(status: QtQmlStatus?, content: QtQuickViewContent?) {
Log.v(TAG, "Status of QtQuickView: $status")
// Show current QML View status in a textview
m_binding.qmlStatusText.text = getString(R.string.qml_view_status, m_statusNames[status])
updateColorDisplay()
if (content == m_firstQmlContent) {
// Connect signal listener to "onClicked" signal from main.qml
// addSignalListener returns int which can be used later to identify the listener
if (status == QtQmlStatus.READY && m_binding.disconnectQmlListenerSwitch.isChecked) {
m_qmlButtonSignalListenerId =
m_firstQmlContent.connectOnClickedListener { _: String, _: Void? ->
Log.i(TAG, "QML button clicked")
m_binding.kotlinRelative.setBackgroundColor(
Color.parseColor(
m_colors.getColor()
)
)
}
}
}
}MainActivity は、QtQuickViewContent.setStatusChangeListener メソッドを使用して、m_mainQmlContent およびm_secondQmlContent のstatusChangeListener として設定されます。
m_firstQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);m_firstQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)オーバーライドされたコールバック関数onStatusChanged() は、現在のQtQuickViewContent がQtQuickViewに読み込まれている際の現在のステータス(QtQmlStatus列挙型)を含むStatusChanged() シグナルを受け取ります。このQtQmlStatus がQtQmlStatus.READY であることが確認されたら、QMLビューとのやり取りを開始できます。
QMLコンポーネントのプロパティ値の取得と設定
QMLコンポーネントのプロパティ値の取得と設定は、Main.java クラスで定義されているメソッドを通じて行われます。この場合、m_mainQmlContent.setColorStringProperty() およびm_mainQmlContent.getColorStringProperty() メソッドを使用します。これらのメソッドは、QMLコンポーネントが持つプロパティに応じて生成されます。
public void onClickListener() {
// Set the QML view root object property "colorStringFormat" value to
// color from Colors.getColor()
m_firstQmlContent.setColorStringFormat(m_colors.getColor());
updateColorDisplay();
}
private void updateColorDisplay() {
String qmlBackgroundColor = m_firstQmlContent.getColorStringFormat();
// Display the QML View background color code
m_qmlViewBackgroundText.setText(qmlBackgroundColor);
// Display the QML View background color in a view
// if qmlBackGroundColor is not null
if (qmlBackgroundColor != null) {
m_colorBox.setBackgroundColor(Color.parseColor(qmlBackgroundColor));
}
}private fun onClickListener() {
// Set the QML view root object property "colorStringFormat" value to
// color from Colors.getColor()
m_firstQmlContent.colorStringFormat = m_colors.getColor()
updateColorDisplay()
}
private fun updateColorDisplay() {
val qmlBackgroundColor = m_firstQmlContent.colorStringFormat
// Display the QML View background color code
m_binding.qmlViewBackgroundText.text = qmlBackgroundColor
// Display the QML View background color in a view
// if qmlBackgroundColor is not null
if (qmlBackgroundColor != null) {
m_binding.qmlColorBox.setBackgroundColor(Color.parseColor(qmlBackgroundColor))
}
}m_mainQmlContent.setColorStringProperty() メソッドを使用して、m_mainQmlContent のcolorStringFormat プロパティの値を、Colors.java (またはColors.kt )クラスから取得したランダムな色値に設定します。
ここでは、m_mainQmlContent.getColorStringProperty() メソッドを使用して、m_mainQmlContentのルートオブジェクトの現在の背景色を取得し、アプリケーションのJava/Kotlin Android側でユーザーに表示しています。
m_secondQmlContent Grid というQMLコンポーネントがあり、生成された メソッドを使用して、Java側からこれを回転させることができます。m_secondQmlContent.setGridRotation()
private void rotateQmlGrid() {
Integer previousGridRotation = m_secondQmlContent.getGridRotation();
if (previousGridRotation != null) {
m_secondQmlContent.setGridRotation(previousGridRotation + 45);
}
}private fun rotateQmlGrid() {
val previousGridRotation = m_secondQmlContent.gridRotation
if (previousGridRotation != null) {
m_secondQmlContent.gridRotation = previousGridRotation + 45
}
}シグナルリスナー
QtQuickViewContent クラスは、connectSignalListener() およびdisconnectSignalListener() メソッドを提供しており、これらはQMLコンポーネントのルートオブジェクトで宣言されたシグナル間のシグナルリスナーの接続および切断に使用されます。QtQuickViewContent.connectSignalListener() は一意のシグナルリスナーIDを返すため、これを保存しておき、後でリスナーを特定して切断する際に使用します。
ここでは、QMLコンポーネントのonClicked() シグナルにシグナルリスナーを接続します:
if (qtQmlStatus == QtQmlStatus.READY && m_switch.isChecked()) {
m_qmlButtonSignalListenerId = m_firstQmlContent.connectOnClickedListener(
(String name, Void v) -> {
Log.i(TAG, "QML button clicked");
m_androidControlsLayout.setBackgroundColor(Color.parseColor(
m_colors.getColor()
));
});
}if (status == QtQmlStatus.READY && m_binding.disconnectQmlListenerSwitch.isChecked) {
m_qmlButtonSignalListenerId =
m_firstQmlContent.connectOnClickedListener { _: String, _: Void? ->
Log.i(TAG, "QML button clicked")
m_binding.kotlinRelative.setBackgroundColor(
Color.parseColor(
m_colors.getColor()
)
)
}
}QMLコンポーネントのボタンがクリックされるたびに、「onClicked() 」シグナルが発信されます。このリスナーはそのシグナルを受信し、アプリケーションのAndroid側を格納するレイアウトの背景色を、Colors.java クラスから取得したランダムな色値に設定します。
次に、QtQuickViewContent.disconnectSignalListener() メソッドを呼び出し、一意のシグナルリスナー ID を指定することで、シグナルリスナーを解除します。
m_firstQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId);m_firstQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId)まだご覧になっていない方は、この例で参照されているツールやAPIを紹介する「Qt Academy:AndroidアプリへのQt Quick 3Dコンテンツの組み込み」コースをぜひチェックしてみてください。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.