La création de colonnes dans une ListView en QML

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 !

Article lu   fois.

Les deux auteurs

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 :

Image non disponible

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

Image non disponible

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.

 
Sélectionnez
// 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é.

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

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

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

 
Sélectionnez
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"
    }
}

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

Creative Commons Attribution-ShareAlike 2.5 Generic