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

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 Donner une note à l'article (5)

Article lu   fois.

Les deux auteurs

Site personnel

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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
Sélectionnez
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
Sélectionnez
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
Sélectionnez
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 :

Image non disponible
QML ne serait-il pas amusant ?

V. Remerciements

Merci à Claude Leloup pour sa relecture attentive !

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

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.