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 Qml 项目,您可以使用“Qt Tools for Android Studio”插件将其导入 Android Studio。其中包含 Java 和 Kotlin 项目,这些项目通过利用QtQuickViewAPI 将该 Qt Qml 项目用作视图。
有关 QML 工作原理的更多信息,请参阅 Qt Qml。本文档重点介绍如何使用 Java 或 Kotlin 将 QML 组件嵌入到 Android 应用程序中。
Qt Quick 对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 引擎或加载任何 QML 文件,因为这些操作后续将由Qt Quick 的视图 API 处理。我们只需在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 设置了两个 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 类
当构建Qt Quick 项目时,会生成对应 QML 类型的 Java 类。在 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 组件:
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()
)
)
}
}
}
}通过调用QtQuickViewContent.setStatusChangeListener 方法,将MainActivity 设置为m_mainQmlContent 和m_secondQmlContent 的statusChangeListener 。
m_firstQmlContent.setStatusChangeListener(this);
m_secondQmlContent.setStatusChangeListener(this);m_firstQmlContent.setStatusChangeListener(this)
m_secondQmlContent.setStatusChangeListener(this)被重写的回调函数onStatusChanged() 会接收StatusChanged() 信号,该信号包含当前QtQuickViewContent 在QtQuickView中加载状态的QtQmlStatus枚举值。如果确认该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 组件,我们可以借助生成的m_secondQmlContent.setGridRotation() 方法从 Java 端对其进行旋转。
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,我们将该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)如果您尚未学习过,请查看“Qt Academy:在 Android 应用中嵌入Qt Quick 3D 内容”课程,该课程介绍了本示例中提到的工具和 API。
© 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.