Qt Quick Android Studio 프로젝트용

Qt Quick Android용 API 예제는 Android Studio 프로젝트입니다
Android용 Qt Quick 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 프로젝트가 포함되어 있습니다. 또한 QtQuickView API를 활용하여 해당 Qml 프로젝트를 뷰(View)로 사용하는 Java 및 Kotlin 프로젝트가 있습니다.
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 엔진을 생성하거나, 나중에 Qt Quick 뷰 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에 대해 두 개의 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 코드 생성에 대한 자세한 내용은 QT_ANDROID_GENERATE_JAVA_QTQUICKVIEW_CONTENTS CMake 변수를참조하십시오 .
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 프로젝트에서는 View 바인딩을 사용하여 애플리케이션의 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 자바 클래스는 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 콘텐츠는 QtQuickViewContent를 인수로 받는 QtQuickView.loadContent() 메서드를 통해 로드됩니다.
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 클래스는 QML 컴포넌트의 루트 객체에 선언된 신호 간에 신호 리스너를 연결하거나 해제하는 데 사용되는 ` connectSignalListener() ` 및 ` disconnectSignalListener() ` 메서드를 제공합니다. ` 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 ’ 클래스에서 가져온 임의의 색상 값으로 설정합니다.
다음으로, 고유한 시그널 리스너 ID를 전달하여 ` QtQuickViewContent.disconnectSignalListener() ` 메서드를 통해 시그널 리스너의 연결을 해제합니다.
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.