Qt Quick Android Studioプロジェクト用

概要

この例では、Qt Tools for Android Studioプラグインを使用してAndroid StudioにインポートできるQMLプロジェクトと、QtQuickViewAPIを利用してQMLプロジェクトをViewとして使用するJavaおよびKotlinプロジェクトを紹介します。

QMLの仕組みについては Qt Qml.このドキュメントでは、QMLコンポーネントをJavaやKotlinベースのAndroidアプリケーションに組み込む方法に焦点を当てます。

まず、JavaとKotlinプロジェクトのMainActivity'のonCreate()メソッドを見てみましょう。

Javaベースのプロジェクトの場合

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    m_mainLinear = findViewById(R.id.mainLinear);
    m_getPropertyValueText = findViewById(R.id.getPropertyValueText);
    m_qmlStatus = findViewById(R.id.qmlStatusText);
    m_androidControlsLayout = findViewById(R.id.javaLinear);
    m_box = findViewById(R.id.qmlColorBox);
    m_switch = findViewById(R.id.disconnectQmlListenerSwitch);
    m_switch.setOnClickListener(view -> switchListener());
    m_qtQuickView = new QtQuickView(this);

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_mainQmlContent.setStatusChangeListener(this);
    m_secondQmlContent.setStatusChangeListener(this);
    ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    m_qmlFrameLayout = findViewById(R.id.qmlFrame);
    m_qmlFrameLayout.addView(m_qtQuickView, params);
    m_qtQuickView.loadContent(m_mainQmlContent);

    Button m_changeColorButton = findViewById(R.id.changeQmlColorButton);
    m_changeColorButton.setOnClickListener(view -> onClickListener());
    Button m_loadMainQmlButton = findViewById(R.id.loadMainQml);
    m_loadMainQmlButton.setOnClickListener(view -> loadMainQml());
    Button m_loadSecondQmlButton = findViewById(R.id.loadSecondQml);
    m_loadSecondQmlButton.setOnClickListener(view -> loadSecondQml());
    Button m_rotateQmlGridButton = findViewById(R.id.rotateQmlGridButton);
    m_rotateQmlGridButton.setOnClickListener(view -> rotateQmlGrid());

    // Check target device orientation on launch
    handleOrientationChanges();
}

Kotlinベースのプロジェクトの場合:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    m_binding = ActivityMainBinding.inflate(layoutInflater)
    val view = m_binding.root
    setContentView(view)

    m_binding.disconnectQmlListenerSwitch.setOnClickListener { switchListener() }

    m_qtQuickView = QtQuickView(this)

    // Set status change listener for m_qmlView
    // listener implemented below in OnStatusChanged
    m_mainQmlContent.setStatusChangeListener(this)
    m_secondQmlContent.setStatusChangeListener(this)

    val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
    )
    m_binding.qmlFrame.addView(m_qtQuickView, params)
    m_qtQuickView!!.loadContent(m_mainQmlContent)

    m_binding.changeQmlColorButton.setOnClickListener { onClickListener() }
    m_binding.loadMainQml.setOnClickListener { loadMainQml() }
    m_binding.loadSecondQml.setOnClickListener { loadSecondQml() }
    m_binding.rotateQmlGridButton.setOnClickListener { rotateQmlGrid() }

    // Check target device orientation on launch
    handleOrientationChanges()
}

注: Kotlinプロジェクトでは、アプリケーションのUIコンポーネントにアクセスするためにViewバインディングを使用しています:

m_binding = ActivityMainBinding.inflate(layoutInflater)
val view = m_binding.root
setContentView(view)

onCreate() メソッドの内部で、以前に宣言された変数m_qtQuickView が新しいQtQuickView で初期化されます。このQtQuickViewの新しいインスタンスは、Java/KotlinアクティビティのContextを引数として与えることで作成されます。

Javaベースのプロジェクトの場合:

m_qtQuickView = new QtQuickView(this);

Kotlinベースのプロジェクトの場合:

m_qtQuickView = QtQuickView(this)

MainSecond のJavaクラスは、QtQuickViewContent クラスを継承しています。これらのクラスは、インポートしたQMLプロジェクトから生成されます。この例では、QMLコンポーネントをAndroidプロジェクトに組み込む方法を説明します。

Javaベースのプロジェクトの場合:

private final Main m_mainQmlContent = new Main();
private final Second m_secondQmlContent = new Second();

Kotlinベースのプロジェクトの場合(宣言時に初期化されます):

private var m_mainQmlContent: Main = Main()
private val m_secondQmlContent: Second = Second()

QtQuickViewContent を引数とするQtQuickView.loadContent() メソッドを通して、m_mainQmlContentm_qtQuickView に読み込みます。

Javaベースのプロジェクトの場合:

m_qtQuickView.loadContent(m_mainQmlContent);

Kotlinベースのプロジェクトの場合:

m_qtQuickView!!.loadContent(m_mainQmlContent)

m_qtQuickView が、適切なレイアウト・パラメータを持つ Android FrameLayout ViewGroup に追加されます。

Javaベースのプロジェクトの場合:

ViewGroup.LayoutParams params = new FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
m_qmlFrameLayout = findViewById(R.id.qmlFrame);
m_qmlFrameLayout.addView(m_qtQuickView, params);

Kotlinベースのプロジェクトの場合:

val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
m_binding.qmlFrame.addView(m_qtQuickView, params)

QMLコンポーネントとの対話

埋め込まれた QML コンポーネントと対話するために、QtQmlStatusChangeListener インターフェースを実装し、onStatusChanged メソッドをオーバーライドして、現在m_qtQuickView に読み込まれている QtQuickViewContent の読み込みステータスを取得します。

Javaベースのプロジェクトの場合:

public class MainActivity extends AppCompatActivity implements
QtQmlStatusChangeListener{
    ...
}

Kotlinベースのプロジェクトの場合:

class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener{
    ...
}

onStatusChanged

Javaベースのプロジェクトの場合:

@Override
public void onStatusChanged(QtQmlStatus qtQmlStatus) {
    Log.i(TAG, "Status of QtQuickView: " + qtQmlStatus);

    final String qmlStatus = getResources().getString(R.string.qml_view_status)
            + m_statusNames.get(qtQmlStatus);

    // Show current QML View status in a textview
    m_qmlStatus.setText(qmlStatus);

    // 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_mainQmlContent.connectOnClickedListener(
                (String name, Void v) -> {
                    Log.i(TAG, "QML button clicked");
                    m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                            m_colors.getColor()
                    ));
                });

    }
}

Kotlinベースのプロジェクトの場合:

override fun onStatusChanged(status: QtQmlStatus?) {
    Log.v(TAG, "Status of QtQuickView: $status")

    val qmlStatus = (resources.getString(R.string.qml_view_status)
            + m_statusNames[status])

    // Show current QML View status in a textview
    m_binding.qmlStatusText.text = qmlStatus

    // 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_mainQmlContent.connectOnClickedListener { _: String, _: Void? ->
                Log.i(TAG, "QML button clicked")
                m_binding.kotlinLinear.setBackgroundColor(
                    Color.parseColor(
                        m_colors.getColor()
                    )
                )
            }
    }
}

onStatusChanged のリスナーは、m_mainQmlContentm_secondQmlContentstatusChangeListener として、QtQuickViewContent.setStatusChangeListener(QtQmlStatusChangeListener onStatusChanged()) メソッドで設定されます。

Javaベースのプロジェクトの場合:

m_mainQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);

Kotlinベースのプロジェクトの場合:

m_mainQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)

オーバーライドされたコールバック関数onStatusChanged() は、現在の QtQuickViewContent のm_qtQuickView へのロードの現在のステータス(public Enum QtQmlStatus)を含むStatusChanged() シグナルを受け取ります。 このQtQmlStatusQtQmlStatus.READY であることが確認されれば、QML ビューとのインタラクションを開始できます。

QtQuickViewへのQtQuickViewContentsのロード

QtQuickView.loadContent()メソッドは、QtQuickViewContentを引数にとります。QtQuickView.loadContent()メソッドはQtQuickViewContentを引数にとります。

Javaベースのプロジェクトの場合:

private void loadSecondQml() {
    m_qtQuickView.loadContent(m_secondQmlContent);

    // Reset box color and color text after component reload
    m_box.setBackgroundColor(Color.parseColor("#00ffffff"));
    m_getPropertyValueText.setText("");
}

private void loadMainQml() {
    m_qtQuickView.loadContent(m_mainQmlContent);

    // Reset box color and color text after component reload
    m_box.setBackgroundColor(Color.parseColor("#00ffffff"));
    m_getPropertyValueText.setText("");
}

Kotlinベースのプロジェクトの場合:

private fun loadSecondQml() {
    m_qtQuickView!!.loadContent(m_secondQmlContent)

    // Reset box color and color text after component reload
    m_binding.qmlColorBox.setBackgroundColor(Color.parseColor("#00ffffff"))
    m_binding.getPropertyValueText.text = ""
}

private fun loadMainQml() {
    m_qtQuickView!!.loadContent(m_mainQmlContent)

    // Reset box color and color text after component reload
    m_binding.qmlColorBox.setBackgroundColor(Color.parseColor("#00ffffff"))
    m_binding.getPropertyValueText.text = ""
}

QMLコンポーネントのプロパティ値の取得と設定

QMLコンポーネントのプロパティ値の取得と設定は、Main.java クラスに記述されているメソッドで行います。ここではm_mainQmlContent.setColorStringProperty()m_mainQmlContent.getColorStringProperty() のメソッドを使います。これらのメソッドは、QMLコンポーネントのプロパティに応じて生成されます。

Javaベースのプロジェクトの場合:

public void onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_mainQmlContent.setColorStringFormat(m_colors.getColor());

    String qmlBackgroundColor = m_mainQmlContent.getColorStringFormat();
    // Display the QML View background color code
    m_getPropertyValueText.setText(qmlBackgroundColor);

    // Display the QML View background color in a view
    // if qmlBackGroundColor is not null
    if (qmlBackgroundColor != null) {
        m_box.setBackgroundColor(Color.parseColor(qmlBackgroundColor));
    }
}

Kotlinベースのプロジェクトの場合:

private fun onClickListener() {
    // Set the QML view root object property "colorStringFormat" value to
    // color from Colors.getColor()
    m_mainQmlContent.colorStringFormat = m_colors.getColor()

    val qmlBackgroundColor = m_mainQmlContent.colorStringFormat

    // Display the QML View background color code
    m_binding.getPropertyValueText.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_mainQmlContentcolorStringFormat プロパティ値に、Colors.java (またはColors.kt )クラスから取得したランダムな色値を設定します。

m_mainQmlContent.getColorStringProperty() メソッドは、m_mainQmlContent のルート・オブジェクトの現在の背景色を取得し、Java/Kotlin Android アプリケーション側でユーザーに表示するために使用します。

m_secondQmlContent Grid QMLコンポーネントがあり、生成された メソッドを使ってJava側から回転させることができます。m_secondQmlContent.setGridRotation()

Javaベースのプロジェクトの場合:

private void rotateQmlGrid() {
    Integer previousGridRotation = m_secondQmlContent.getGridRotation();
    if (previousGridRotation != null) {
        m_secondQmlContent.setGridRotation(previousGridRotation + 45);
    }
}

Kotlinベースのプロジェクトの場合:

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() シグナルに接続します。

Javaベースのプロジェクトの場合:

if (qtQmlStatus == QtQmlStatus.READY && !m_switch.isChecked()) {
    m_qmlButtonSignalListenerId = m_mainQmlContent.connectOnClickedListener(
            (String name, Void v) -> {
                Log.i(TAG, "QML button clicked");
                m_androidControlsLayout.setBackgroundColor(Color.parseColor(
                        m_colors.getColor()
                ));
            });

}

Kotlinベースのプロジェクトの場合:

if (status == QtQmlStatus.READY && !m_binding.disconnectQmlListenerSwitch.isChecked) {
    m_qmlButtonSignalListenerId =
        m_mainQmlContent.connectOnClickedListener { _: String, _: Void? ->
            Log.i(TAG, "QML button clicked")
            m_binding.kotlinLinear.setBackgroundColor(
                Color.parseColor(
                    m_colors.getColor()
                )
            )
        }
}

onClicked() シグナルはQMLコンポーネントのボタンがクリックされるたびに発せられます。そのシグナルをこのリスナーが受信し、Android側のレイアウトの背景色がColors.java クラスから取得したランダムな色に設定されます。

次に、QtQuickViewContent.disconnectSignalListener() メソッドを使って、シグナルリスナーに固有のシグナルリスナーIDを与え、シグナルリスナーを切断します。

Javaベースのプロジェクトの場合:

m_mainQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId);

Kotlinベースのプロジェクトの場合:

m_mainQmlContent.disconnectSignalListener(m_qmlButtonSignalListenerId)

© 2025 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.