Qt Quick for 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)

本書に含まれる文書の著作権は、それぞれの所有者に帰属します 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。