Modèle de liste hétérogène en QML

| Christophe Dumez | traducteur : Thibaut Cuvelier |

On va montrer ici comment utiliser ListView pour afficher les données d'un modèle hétérogène. Le problème, ici, est que, en fonction du type de données, on aura un affichage différent, on utilisera donc différents délégués. Le truc est l'utilisation d'un délégué capable de détecter le type de données et ainsi adapter son affichage.

Commentez

- Titre : Modèle de liste hétérogène en QML

- Auteurs : Christophe Dumez, traducteur : Thibaut Cuvelier

- Parution : 6 février 2012

- Mise à jour : 7 août 2012

- Licence : Copyright ® 2012 Christophe Dumez. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. L'article original

- II. Le problème

- III. Un exemple

- IV. Explications

- V. Remerciements

I - L'article original

Cet article est une adaptation en langue française de Heterogeneous List Model in QML.

II - Le problème

On va montrer ici comment utiliser ListView pour afficher les données d'un modèle hétérogène. Le problème, ici, est que, en fonction du type de données, on aura un affichage différent, on utilisera donc différents délégués. Le truc est l'utilisation d'un délégué capable de détecter le type de données et ainsi adapter son affichage.

III - Un exemple

On considère un exemple simple : un modèle QML (ListModel) qui contient du texte et des images.

DataBank.qml

import QtQuick 1.0

ListModel {
id: dataBank

ListElement {
value: "http://www.wondericons.com/dogs/myspace_dogs_icons_02.gif"
type: "image"
}
ListElement {
value: "Dummy text 1"
type: "text"
}
ListElement {
value: "http://www.wondericons.com/dogs/myspace_dogs_icons_08.gif"
type: "image"
}
ListElement {
value: "Dummy text 2"
type: "text"
}
}

On crée alors une ListView pour afficher ce modèle :

main.qml

import QtQuick 1.0

Rectangle {
width: 360
height: 360
ListView {
id: dataView
anchors.fill: parent
spacing: 2
model: DataBank{}
delegate: MultiDelegate{}
}
}

Cette vue utilise le modèle DataBank et utilisera MultiDelegate comme délégué. Le code de ce délégué est la partie intéressante, parce qu'il doit afficher des images et du texte.

Voici une manière d'atteindre le comportement voulu :

MultiDelegate.qml

import QtQuick 1.0

Item {
id: multiDelegate
height: 80
width: multiDelegate.ListView.view.width

function bestDelegate(t) {
if(t == "image")
return imgDelegate;
return txtDelegate; // t == "text"
}

Component {
id: imgDelegate

Image {
id: img
source: value
fillMode: Image.PreserveAspectFit
asynchronous: true
}
}

Component {
id: txtDelegate

Text {
id: txt
text: value
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}

Loader {
id: itemDisplay
anchors.fill: parent;
anchors.topMargin: 2
anchors.bottomMargin: 2
sourceComponent: bestDelegate(type)
}

Rectangle {
id: separator
width: parent.width; height: 1; color: "#cccccc"
anchors.bottom: parent.bottom
}
}

IV - Explications

Les Component de QML sont utilisés pour définir les deux sous-délégués (imgDelegate et txtDelegate). Le fait est que les items dans un composant ne sont pas automatiquement rendus et affichés.

Il est alors possible d'utiliser un Loader pour charger dynamiquement et afficher l'un des deux composants. La tâche qu'il reste à faire est d'écrire du code JavaScript pour sélectionner le sous-délégué le plus approprié, en se basant sur le type de données. C'est le but de la fonction bestDelegate().

Voici ce à quoi cela ressemble :

QML ne serait-il pas amusant ?

V - Remerciements

Merci à Claude Leloup pour sa relecture attentive !