Sur cette page

Exposition de QtAbstractListModel à QML

Qt Quick Les exemples d'API Android sont des projets Android Studio

Les exemples d'API « Qt Quick » pour Android sont fournis sous forme de projets Android Studio. Les dossiers de projet se trouvent dans le répertoire d'installation de Qt.

Par exemple, sous le chemin d'installation par défaut sous Windows, ils se trouvent ici :

C:\Qt\Examples\Qt-<patch-release-number>\platforms\android\<example-name>

Ces projets sont déjà configurés pour utiliser une version du plugin Gradle Qt compatible avec cette version de Qt.

Présentation

Application Android avec une ListView affichant l'UUID et les données des lignes, dotée de boutons « Ajouter une ligne » et « Supprimer une ligne »

Cet exemple se compose de deux projets distincts : un projet QML et un projet Android basé sur Kotlin qui hébergera et affichera le contenu QML. Il montre comment utiliser QtAbstractListModel pour partager des données depuis le côté Android vers la vue QML qui affiche les données à l'aide d'une ListView.

Exécution de l’exemple

Pour exécuter cet exemple, vous devez disposer d’Android Studio et d’une installation de Qt pour Android.

Le plugin Gradle Qt sera utilisé pour compiler le projet Qml lors du processus de compilation du projet Android. À cet effet, l’exemple contient des paramètres de configuration du plugin dans le fichier build.gradle.kts au niveau de l’application ; ceux-ci devront peut-être être modifiés si le plugin ne parvient pas, par exemple, à localiser le répertoire du kit Qt.

QtBuild {
    // Relative for Qt (Installer or MaintenanceTool) installations.
    qtPath = file("../../../../../../../6.12.0")
    projectPath = file("../../qtabstractlistmodel")
}

Pour plus d’informations sur la configuration du plugin, veuillez vous reporter à la documentation du plugin Gradle Qt.

Projet QML

Le projet QML est assez simple : il définit un modèle de données en tant que propriété de l’objet racine, ainsi que quelques éléments d’interface utilisateur destinés à afficher les données issues de ce modèle.

Rectangle {
    id: mainRectangle

    property AbstractItemModel dataModel

Pour afficher les données du modèle, un ` ListView ` est créé. La propriété ` model ` est ensuite définie sur le modèle de données déclaré précédemment.

    ListView {
        id: listView

        model: mainRectangle.dataModel

Afin d’afficher le modèle de données, l’ ListView a besoin d’un délégué qui sera instancié pour chaque élément du modèle de données. Dans ce cas, le délégué sera un Rectangle contenant deux éléments Text dans un Column, affichant les données de chaque élément du modèle de données.

        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
                }
            }
        }

Projet Kotlin

Le côté Android se compose d’une seule activité et de la définition du modèle de données utilisé précédemment dans la vue QML.

Modèle de données

Le modèle de données MyListModel est une classe dérivée de QtAbstractListModel, utilisant ArrayList<String> comme système de stockage interne des données. Dans le bloc d’initialisation de MyListModel, il génère des données aléatoires pour la liste.

class MyListModel : QtAbstractListModel() {
    private val m_dataList = ArrayList<String>()

    init {
        synchronized(this) {
            for (row in 0..4) {
                m_dataList.add(UUID.randomUUID().toString())
            }
        }
    }

Chaque élément du modèle est associé à un ensemble d’éléments de données, chacun ayant son propre rôle. Les implémentations personnalisées de QtAbstractItemModel doivent définir un rôle personnalisé pour chaque élément de données. Chaque rôle est associé à une valeur de type int, utilisée lors de la récupération des données, et à une valeur de type chaîne de caractères, qui spécifie le nom de l’élément de données lorsqu’il est utilisé depuis QML.

    @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
    }

Alors que les valeurs d’ Int s de la méthode ` "roleNames()" ` peuvent être codées en dur, cet exemple spécifie une classe d’énumération personnalisée ` DataRole ` dans ` MyListModel`, qui est utilisée pour faire référence à ces valeurs. Dans cet exemple, nous définissons deux rôles : `UUID` et `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
            }
        }
    }

Pour renvoyer des données à partir du modèle de données, la classe doit redéfinir la méthode ` "QtAbstractListModel::data()" `. Cette méthode prend deux paramètres : `QtModelIndex` et ` Int`, qui font respectivement référence à l’index et au rôle de l’élément de données.

Dans "MyDataModel::data()", le rôle UUID renvoie les données de l’index donné dans les données internes, tandis que le rôle Row renvoie la ligne de l’élément demandé.

Remarque : cette méthode, ainsi que certaines autres, est annotée avec une balise @Synchronized. Cela s’explique par le fait que les appels à ces méthodes proviennent du thread Qt et accèdent aux données sous-jacentes, éventuellement en même temps que les requêtes provenant du thread Android via les méthodes "addRow()" et "removeRow()".

    @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 -> ""
        }
    }

Pour permettre à des acteurs externes de manipuler le `QtAbstractItemModel`, l'exemple ajoute deux méthodes supplémentaires à ` MyDataModel`. Pour ajouter des données à la ligne, il dispose de la méthode ` "addRow()" ` ; pour supprimer des données, il existe la méthode ` "removeRow()" `. Celles-ci sont utilisées depuis l'activité principale.

    @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()
        }
    }

Activité principale

La classe ` MainActivity ` est une simple activité (Activity) basée sur Kotlin, mais elle implémente également l’interface `QtQmlStatusChangeListener` pour écouter les événements liés à l’état de chargement du QML. Elle stocke également l’objet `QtQuickViewContent` correspondant à la vue principale de l’application QML, ainsi qu’une instance du modèle de données décrit ci-dessus.

class MainActivity : AppCompatActivity(), QtQmlStatusChangeListener {
    private val m_mainQmlContent: Main = Main()
    private val m_listModel = MyListModel()

Lors de la création de l’activité principale de l’application, l’exemple commence par créer un QtQuickView et l’intègre dans la hiérarchie des vues.

        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)

Après avoir ajouté le QtQuickView à l’interface utilisateur, l’exemple identifie les boutons utilisés pour manipuler le modèle de données et définit des écouteurs de clic afin d’appeler les méthodes ` addRow() ` et ` removeRow() ` sur le modèle de données associé.

        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()
        }

Une fois la configuration de l’interface utilisateur et la mise en place des écouteurs terminées, le composant QML peut être préparé et chargé. L’exemple définit la méthode ` MainActivity ` comme écouteur du signal de changement d’état du composant QML et demande à QtQuickView de charger ce composant.

        m_mainQmlContent.setStatusChangeListener(this)
        qtQuickView.loadContent(m_mainQmlContent)

Enfin, une fois le composant QML chargé avec succès, l’exemple attribue la valeur de l’instance MyDataModel à la propriété dataModel du composant QML.

    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.