QtAbstractListModel을 QML에 노출하기
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 플러그인 버전을 사용하도록 이미 구성되어 있습니다.
개요

이 예제는 QML 프로젝트와 QML 콘텐츠를 호스팅하고 표시하는 Kotlin 기반 Android 프로젝트, 이렇게 두 개의 별도 프로젝트로 구성됩니다. 이 예제는 QtAbstractListModel을 사용하여 Android 측의 데이터를 ListView 을 통해 데이터를 표시하는 QML 뷰로 공유하는 방법을 보여줍니다.
예제 실행
이 예제를 실행하려면 Android Studio와 Qt for Android가 설치되어 있어야 합니다.
Android 프로젝트 빌드 과정에서 Qt Gradle 플러그인을 사용하여 Qml 프로젝트를 빌드합니다. 이를 위해 예제에는 앱 수준의 build.gradle.kts 파일에 플러그인 구성이 포함되어 있으며, 예를 들어 플러그인이 Qt 키트 디렉터리를 찾을 수 없는 경우 이 구성을 수정해야 할 수도 있습니다.
QtBuild {
// Relative for Qt (Installer or MaintenanceTool) installations.
qtPath = file("../../../../../../../6.12.0")
projectPath = file("../../qtabstractlistmodel")
}플러그인에 대한 추가 구성 사항은 Qt Gradle 플러그인 문서를 참조하십시오.
QML 프로젝트
QML 프로젝트는 매우 간단하며, 루트 객체의 속성으로 데이터 모델을 정의하고 해당 모델의 데이터를 표시할 몇 가지 UI 요소를 정의합니다.
Rectangle {
id: mainRectangle
property AbstractItemModel dataModel모델의 데이터를 표시하기 위해 ` ListView `가 생성됩니다. 그런 다음 ` model ` 속성을 앞서 선언한 데이터 모델로 설정합니다.
ListView {
id: listView
model: mainRectangle.dataModel데이터 모델을 표시하기 위해 ` ListView `에는 데이터 모델의 각 항목에 대해 인스턴스화될 델리게이트가 필요합니다. 이 경우, 델리게이트는 ` Column` 내에 두 개의 ` Text ` 요소를 포함하는 ` Rectangle `이며, 데이터 모델의 각 요소에 있는 데이터를 표시합니다.
delegate: Rectangle {
required property var model
width: listView.width
height: textColumn.height + (2 * textColumn.spacing)
color: "#2CDE85"
radius: 25
Column {
id: textColumn
height: idText.height + rowText.height + spacing
spacing: 15
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
right: parent.right
leftMargin: 20
rightMargin: 20
}
Text {
id: idText
color: "#00414A"
text: model.id
font.pixelSize: 36
font.bold: true
}
Text {
id: rowText
color: "#00414A"
text: model.row
font.pixelSize: 36
font.bold: true
}
}
}Kotlin 프로젝트
Android 측에는 단일 Activity 와 앞서 QML 뷰에서 사용된 데이터 모델의 정의가 포함됩니다.
데이터 모델
데이터 모델 MyListModel 은 QtAbstractListModel의 자식 클래스이며, ArrayList<String> 을 데이터의 내부 저장 시스템으로 사용합니다. MyListModel 의 초기화 블록에서는 목록에 사용할 임의의 데이터를 생성합니다.
class MyListModel : QtAbstractListModel() {
private val m_dataList = ArrayList<String>()
init {
synchronized(this) {
for (row in 0..4) {
m_dataList.add(UUID.randomUUID().toString())
}
}
}모델의 각 항목에는 일련의 데이터 요소가 연관되어 있으며, 각 요소는 고유한 역할을 가집니다. QtAbstractItemModel을 사용자 정의로 구현할 때는 각 데이터 요소에 대해 사용자 정의 역할을 정의해야 합니다. 각 역할에는 데이터를 가져올 때 사용되는 연관된 Int 값과, QML에서 사용할 때 데이터 요소의 이름을 지정하는 String 값이 있습니다.
@Synchronized
override fun roleNames(): HashMap<Int, String> {
val m_roles = HashMap<Int, String>()
m_roles[DataRole.UUID.value()] = "id"
m_roles[DataRole.Row.value()] = "row"
return m_roles
}"roleNames()" 메서드 내의 Int 값은 하드코딩될 수 있지만, 이 예제에서는 MyListModel 내에 사용자 정의 열거형 클래스 DataRole 를 지정하며, 이 값을 참조할 때 사용됩니다. 이 예제에서는 UUID와 Row라는 두 가지 역할을 정의합니다.
private enum class DataRole(val m_value: Int) {
UUID(0),
Row(1);
fun value(): Int {
return m_value
}
companion object {
fun valueOf(value: Int): DataRole? {
val values = entries.toTypedArray()
if (0 <= value && value < values.size) return values[value]
return null
}
}
}데이터 모델에서 데이터를 반환하려면 해당 클래스가 ` "QtAbstractListModel::data()" ` 메서드를 재정의해야 합니다. 이 메서드는 데이터 요소의 인덱스와 역할을 각각 나타내는 ` QtModelIndex `와 ` Int`라는 두 개의 매개변수를 받습니다.
"MyDataModel::data()" 에서 UUID 역할은 내부 데이터의 지정된 인덱스에서 데이터를 반환하는 반면, Row 역할은 요청된 요소의 행을 반환합니다.
참고: 이 메서드는 다른 몇 가지 메서드와 함께 @Synchronized 태그로 주석이 달렸습니다. 이는 Qt 스레드에서 호출되는 이 메서드들이 "addRow()" 및 "removeRow()" 메서드를 통해 Android 스레드에서 전송된 요청과 동시에 기본 데이터에 접근할 가능성이 있기 때문입니다.
@Synchronized
override fun data(qtModelIndex: QtModelIndex, role: Int): Any {
return when (DataRole.valueOf(role)) {
DataRole.UUID -> "UUID: " + m_dataList[qtModelIndex.row()]
DataRole.Row -> "Row: " + qtModelIndex.row()
else -> ""
}
}외부 액터가 QtAbstractItemModel을 조작할 수 있도록 하기 위해, 이 예제에서는 MyDataModel 에 두 가지 메서드를 추가합니다. 행에 데이터를 추가하기 위한 "addRow()" 메서드와, 데이터를 제거하기 위한 "removeRow()" 메서드가 있습니다. 이 메서드들은 메인 액티비티에서 사용됩니다.
@Synchronized
fun addRow() {
beginInsertRows(QtModelIndex(), m_dataList.size, m_dataList.size)
m_dataList.add(UUID.randomUUID().toString())
endInsertRows()
}
@Synchronized
fun removeRow() {
if (!m_dataList.isEmpty()) {
beginRemoveRows(QtModelIndex(), m_dataList.size - 1, m_dataList.size - 1)
m_dataList.removeAt(m_dataList.size - 1)
endRemoveRows()
}
}메인 액티비티
MainActivity 클래스는 간단한 Kotlin 기반 Activity이지만, QML 로딩 상태 이벤트를 수신하기 위해 QtQmlStatusChangeListener 인터페이스도 구현합니다. 또한 이 클래스는 QML 애플리케이션의 메인 뷰에 대한 QtQuickViewContent 객체와 앞서 설명한 데이터 모델의 인스턴스를 저장합니다.
class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener {
private val m_mainQmlContent: Main = Main()
private val m_listModel = MyListModel()애플리케이션의 메인 액티비티를 생성할 때, 이 예제는 먼저 QtQuickView를 생성하여 뷰 계층 구조에 배치합니다.
val qtQuickView: QtQuickView = QtQuickView(this)
val params: ViewGroup.LayoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
val qmlFrameLayout: FrameLayout = findViewById<FrameLayout>(R.id.qmlFrame)
qmlFrameLayout.addView(qtQuickView, params)UI에 QtQuickView를 추가한 후, 이 예제는 데이터 모델을 조작하는 데 사용되는 버튼을 찾아, 데이터 모델의 멤버 메서드인 ` addRow() `와 ` removeRow() `를 호출하도록 몇 가지 클릭 리스너를 설정합니다.
val addRowAtEndButton: Button = findViewById<Button>(R.id.addRow)
val removeRowFromEndButton: Button = findViewById<Button>(R.id.removeRow)
addRowAtEndButton.setOnClickListener { _: View? ->
m_listModel.addRow()
}
removeRowFromEndButton.setOnClickListener { _: View? ->
m_listModel.removeRow()
}UI 설정과 리스너 설정이 완료되면 QML 컴포넌트를 준비하고 로드할 수 있습니다. 이 예제에서는 MainActivity 를 QML 컴포넌트의 상태 변경 신호에 대한 리스너로 설정하고, QtQuickView에 QML 컴포넌트를 로드하도록 지시합니다.
m_mainQmlContent.setStatusChangeListener(this)
qtQuickView.loadContent(m_mainQmlContent)마지막으로, QML 컴포넌트가 성공적으로 로드되면 이 예제는 MyDataModel 인스턴스의 값을 QML 컴포넌트의 dataModel 속성에 할당합니다.
override fun onStatusChanged(qtQmlStatus: QtQmlStatus) {
if (qtQmlStatus === QtQmlStatus.READY) {
m_mainQmlContent.setDataModel(m_listModel)
}
}© 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.