La création de colonnes dans une ListView en QML

| traducteur : Thibaut Cuvelier | Qt Developer Network |

Ici sera présentée une méthode pour créer une ListView avec plusieurs colonnes dont les largeurs dépendent de la taille des données dans toute la colonne, pas seulement dans la cellule.

Commentez !

- Titre : La création de colonnes dans une ListView en QML

- Auteurs : traducteur : Thibaut Cuvelier, Qt Developer Network

- Parution : 5 janvier 2011

- Mise à jour : 17 avril 2011

- Licence : Creative Commons Attribution-ShareAlike 2.5 Generic

Sommaire

- I. L'article original

- II. Le problème

- III. La récupération de la largeur du texte

- IV. Créer des colonnes dans une ListView

- IV-A. main.qml

- IV-B. ColumnHelper.js

- IV-C. MovieItem.qml

- IV-D. MovieModel.qml

I - L'article original

Le Qt Developer Network est un réseau de développeurs utilisant Qt afin de partager leur savoir sur ce framework. Vous pouvez le consulter en anglais.

Nokia, Qt, Qt Quarterly et leurs logos sont des marques déposées de Nokia Corporation en Finlande et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.

Cet article est la traduction de How to create columns in a QML ListView.

Merci à eusebe19 pour sa relecture !

II - Le problème

À la base, une ListView d'éléments Row ressemble à ceci :

Or, on préférerait avoir ce genre de rendu :

III - La récupération de la largeur du texte

La métrique des fontes n'est pas disponible en QML. Cependant, des éléments Text peuvent être créés dynamiquement en JavaScript ; on peut alors leur demander leur largeur.

// Création d'un élément Text temporaire
var textElement = Qt.createQmlObject('import Qt 4.7; Text { text: "' + text + '"}', parent, "calcTextWidth");

// Utilisation de textElement.width pour récupérer la largeur du texte

// Destruction de l'élément temporaire
textElement.destroy()

IV - Créer des colonnes dans une ListView

Les largeurs des colonnes sont calculées pour le modèle avec du JavaScript, stockées dans une structure de données dont les clés sont les noms des éléments du modèle, utilisée dans le délégué de la ListView.

IV-A - main.qml

Une interface simple pour montrer la ListView. Un élément Rectangle est utilisé comme conteneur, simplement pour donner une couleur cohérente avec les couleurs utilisées dans les lignes. Notez que la propriété columnWidths est utilisée pour stocker les largeurs calculées, qui sont ensuite utilisées dans le délégué.

import Qt 4.7
import "ColumnHelper.js" as ColumnHelper

Rectangle {
width: 620
height: 200
color: "#bebebe"

ListView {
id: list
property variant columnWidths: ColumnHelper.calcColumnWidths(model, list)
anchors.fill: parent
model: MovieModel { }
delegate:  MovieItem { }
}

}

IV-B - ColumnHelper.js

Une simple fonction JavaScript est utilisée pour trouver la largeur maximale de l'élément Text parmi tous ceux de chaque colonne et retourne ces valeurs dans un objet indexé selon le nom de la colonne.

var columns = {}

function calcColumnWidths(model, parent)
{
for (var i = 0; i < model.count; ++i)
{
var data = model.get(i)
for (var key in data)
{
if (!columns[key]) {
columns[key] = 0
}

var textElement = Qt.createQmlObject(
'import Qt 4.7;'
+ 'Text {'
+ '   text: "' + data[key] + '" '
+ '}',
parent, "calcColumnWidths")

columns[key] = Math.max(textElement.width, columns[key])
textElement.destroy()
}
}
return columns
}

IV-C - MovieItem.qml

Voici le délégué pour la ListView. La propriété columnWidths de la liste est utilisée pour définir les largeurs des colonnes.

import Qt 4.7

Component {
Item {
id: item
width: parent.width - 15
height: row.height

function altColor(i) {
var colors = [ "#bebebe", "#b7b7b7" ];
return colors[i];
}

Rectangle {
id: background
width:  parent.width + 15
height: parent.height
color: altColor(index%2)
}

Row {
id: row
width: parent.width
spacing: 5
Item {
// Indent a little
width: 5
height: 1
}
Text {
width: list.columnWidths['title']
text: model.title
color: "blue"
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['year']
text: model.year
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['rank']
text: model.rank
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['votes']
text: model.votes
}
Loader { sourceComponent: columnSeparator; height: parent.height }
Text {
width: list.columnWidths['composer']
text: model.composer ? model.composer : ""
}

Component {
id: columnSeparator
Rectangle {
width: 1
color: "black"
opacity: 0.3
}
}
}
}
}

IV-D - MovieModel.qml

Le modèle utilisé ; les données proviennent de l'Internet Movie Database.

import Qt 4.7

ListModel {
ListElement {
votes: 532564
rank: 9.2
title: "The Shawshank Redemption"
year: 1994
composer: "Newman, Thomas"
}
ListElement {
votes: 419312
rank: 9.1
title: "The Godfather"
year: 1972
composer: "Rota, Nino"
}
ListElement {
votes: 251290
rank: 9.0
title: "The Godfather: Part II"
year: 1974
composer: "Rota, Nino"
}
ListElement {
votes: 225000
rank: 8.9
title: "Inception"
year: 2010
composer: "Zimmer, Hans"
}
ListElement {
votes: 165033
rank: 8.9
title: "Il buono, il brutto, il cattivo."
year: 1966
composer: "Morricone, Ennio"
}
ListElement {
votes: 426752
rank: 8.9
title: "Pulp Fiction"
year: 1994
}
ListElement {
votes: 282473
rank: 8.9
title: "Schindler's List"
year: 1993
composer: "Williams, John"
}
ListElement {
votes: 122919
rank: 8.9
title: "12 Angry Men"
year: 1957
composer: "Hopkins, Kenyon"
}
ListElement {
votes: 219739
rank: 8.8
title: "One Flew Over the Cuckoo's Nest"
year: 1975
composer: "Nitzsche, Jack"
}
ListElement {
votes: 476112
rank: 8.8
title: "The Dark Knight"
year: 2008
composer: "Zimmer, Hans"
}
ListElement {
votes: 283354
rank: 8.8
title: "Star Wars: Episode V - The Empire Strikes Back"
year: 1980
composer: "Williams, John"
}
ListElement {
votes: 371790
rank: 8.8
title: "The Lord of the Rings: The Return of the King"
year: 2003
composer: "Shore, Howard"
}
ListElement {
votes: 98799
rank: 8.8
title: "Shichinin no samurai"
year: 1954
composer: "Hayasaka, Fumio"
}
ListElement {
votes: 326619
rank: 8.7
title: "Star Wars"
year: 1977
composer: "Williams, John"
}
ListElement {
votes: 234582
rank: 8.7
title: "Goodfellas"
year: 1990
}
ListElement {
votes: 170874
rank: 8.7
title: "Casablanca"
year: 1942
composer: "Steiner, Max"
}
}