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)
Main
、Second
の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_mainQmlContent
をm_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_mainQmlContent
とm_secondQmlContent
のstatusChangeListener
として、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()
シグナルを受け取ります。 このQtQmlStatus
がQtQmlStatus.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_mainQmlContent
のcolorStringFormat
プロパティ値に、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.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。