Sur cette page

Graphique à barres simple

Utilisation de Bars3D dans une application QML.

Simple Bar Graph montre comment créer un simple graphique à barres en 3D à l'aide de Bars3D et de QML.

Les sections suivantes décrivent comment changer de série et afficher plus d'une série à la fois. Pour plus d'informations sur les fonctionnalités de base d'une application QML, voir Simple Scatter Graph (graphique de dispersion simple).

Exécution de l'exemple

Pour exécuter l'exemple à partir de Qt CreatorOuvrez le mode Welcome et sélectionnez l'exemple à partir de Examples. Pour plus d'informations, voir Qt Creator: Tutoriel : Construire et exécuter.

Données

Les données de l'exemple sont les revenus et les dépenses mensuels d'une entreprise fictive sur plusieurs années. Les données sont définies dans un modèle de liste à l'adresse Data.qml:

ListModel {
    id: dataModel
    ListElement{ timestamp: "2016-01"; expenses: "-4";  income: "5" }
    ListElement{ timestamp: "2016-02"; expenses: "-5";  income: "6" }
    ListElement{ timestamp: "2016-03"; expenses: "-7";  income: "4" }
    ...

Chaque élément de données a trois rôles : l'horodatage, les revenus et les dépenses. La valeur de l'horodatage est au format : <four digit year>-<two digit month>. Habituellement, vous feriez correspondre les années et les mois aux lignes et aux colonnes d'un graphique à barres, mais vous ne pouvez afficher que les revenus ou les dépenses en tant que valeur.

Ajoutez maintenant les données au graphique Bars3D. Créez deux Bar3DSeries à l'intérieur de celui-ci, en commençant par une série pour les revenus :

Bar3DSeries {
    id: barSeries
    itemLabelFormat: "Income, @colLabel, @rowLabel: @valueLabel"
    baseGradient: barGradient

    ItemModelBarDataProxy {
        id: modelProxy
        itemModel: graphData.model
        rowRole: "timestamp"
        columnRole: "timestamp"
        valueRole: "income"
        rowRolePattern: /^(\d\d\d\d).*$/
        columnRolePattern: /^.*-(\d\d)$/
        rowRoleReplace: "\\1"
        columnRoleReplace: "\\1"
        multiMatchBehavior: ItemModelBarDataProxy.MultiMatchBehavior.Cumulative
    }
    ...

Les données sont attachées à la propriété itemModel du ItemModelBarDataProxy à l'intérieur de la série. Pour le champ valueRole, spécifiez le champ income car il contient la valeur souhaitée. L'obtention des années et des mois est un peu plus compliquée puisqu'ils se trouvent dans le même champ. Pour extraire ces valeurs, indiquez le champ timestamp pour rowRole et columnRole. En outre, spécifiez un motif de recherche et une règle de remplacement pour ces rôles afin d'extraire la partie correcte du contenu du champ pour chaque rôle. Le motif de recherche est une expression régulière JavaScript normale, et la règle de remplacement spécifie par quoi le contenu du champ correspondant à l'expression régulière doit être remplacé. Dans ce cas, l'ensemble du contenu du champ est remplacé par l'année ou le mois, qui est la première sous-chaîne capturée pour les lignes et les colonnes. Pour plus d'informations sur la fonctionnalité de remplacement par des expressions régulières, consultez la documentation de la fonction QString::replace(const QRegExp &rx, const QString &after).

La propriété multiMatchBehavior indique ce qu'il convient de faire lorsque plusieurs éléments du modèle d'élément correspondent à la même combinaison ligne/colonne. Dans ce cas, il convient d'additionner leurs valeurs. Cette propriété n'a aucun effet lors de l'affichage des valeurs pour chaque mois, car il n'y a pas de mois en double dans notre modèle d'élément. Cependant, elle devient pertinente plus tard lorsque vous souhaitez afficher les totaux annuels.

Ajoutez ensuite une autre série pour les dépenses :

Bar3DSeries {
    id: secondarySeries
    visible: false
    itemLabelFormat: "Expenses, @colLabel, @rowLabel: -@valueLabel"
    baseGradient: secondaryGradient

    ItemModelBarDataProxy {
        id: secondaryProxy
        itemModel: graphData.model
        rowRole: "timestamp"
        columnRole: "timestamp"
        valueRole: "expenses"
        rowRolePattern: /^(\d\d\d\d).*$/
        columnRolePattern: /^.*-(\d\d)$/
        valueRolePattern: /-/
        rowRoleReplace: "\\1"
        columnRoleReplace: "\\1"
        multiMatchBehavior: ItemModelBarDataProxy.MultiMatchBehavior.Cumulative
    }
    ...

Le modèle contient des dépenses sous forme de valeurs négatives, mais elles pourraient être affichées sous forme de barres positives pour faciliter la comparaison avec les barres de revenus. Utilisez l'adresse valueRolePattern pour supprimer le signe moins, et il n'est pas nécessaire de spécifier une chaîne de remplacement, car la chaîne de remplacement par défaut est une chaîne vide.

Utilisez la propriété visible de la série pour masquer la deuxième série pour l'instant.

Étiquettes d'axe personnalisées

Axes.qml redéfinit les étiquettes de catégorie pour l'axe des colonnes car les données contiennent des nombres pour les mois, ce qui encombrerait les étiquettes :

Category3DAxis {
    id: columnAxis
    labels: ["January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"]
    labelAutoAngle: 30
}

Pour rendre les étiquettes d'axe plus lisibles lorsque l'angle de la caméra est faible, activez la rotation automatique des étiquettes d'axe.

Changement de série

Dans main.qml, configurez le graphique et les divers éléments de l'interface utilisateur. Il y a trois blocs de code intéressants à souligner ici. Le premier montre comment changer les données visualisées entre les revenus, les dépenses et les deux, en changeant simplement la visibilité des deux séries :

onClicked: {
    if (text === "Show Expenses") {
        barSeries.visible = false
        secondarySeries.visible = true
        barGraph.valueAxis.labelFormat = "-%.2f M\u20AC"
        secondarySeries.itemLabelFormat = "Expenses, @colLabel, @rowLabel: @valueLabel"
        text = "Show Both"
    } else if (text === "Show Both") {
        barSeries.visible = true
        barGraph.valueAxis.labelFormat = "%.2f M\u20AC"
        secondarySeries.itemLabelFormat = "Expenses, @colLabel, @rowLabel: -@valueLabel"
        text = "Show Income"
    } else { // text === "Show Income"
        secondarySeries.visible = false
        text = "Show Expenses"
    }
}

Le format de l'étiquette de l'axe et le format de l'étiquette de sélection de l'élément sont modifiés pour que le signe négatif apparaisse correctement pour les dépenses, qui étaient en fait résolues comme des valeurs positives.

Le deuxième bloc intéressant est celui où les données visualisées sont modifiées en ajustant les propriétés du proxy :

onClicked: {
    if (text === "Show yearly totals") {
        modelProxy.autoRowCategories = true
        secondaryProxy.autoRowCategories = true
        modelProxy.columnRolePattern = /^.*$/
        secondaryProxy.columnRolePattern = /^.*$/
        graphAxes.value.autoAdjustRange = true
        barGraph.columnAxis = graphAxes.total
        text = "Show all years"
    } else if (text === "Show all years") {
        modelProxy.autoRowCategories = true
        secondaryProxy.autoRowCategories = true
        modelProxy.columnRolePattern = /^.*-(\d\d)$/
        secondaryProxy.columnRolePattern = /^.*-(\d\d)$/
        graphAxes.value.min = 0
        graphAxes.value.max = 35
        barGraph.columnAxis = graphAxes.column
        text = "Show 2020 - 2022"
    } else { // text === "Show 2020 - 2022"
        // Explicitly defining row categories, since we do not want to show data for
        // all years in the model, just for the selected ones.
        modelProxy.autoRowCategories = false
        secondaryProxy.autoRowCategories = false
        modelProxy.rowCategories = ["2020", "2021", "2022"]
        secondaryProxy.rowCategories = ["2020", "2021", "2022"]
        text = "Show yearly totals"
    }
}

Pour afficher les totaux annuels, il faut combiner les douze mois de chaque année en une seule barre. Pour ce faire, il convient de spécifier une adresse columnRolePattern qui correspond à tous les éléments du modèle. De cette manière, la série n'aura qu'une seule colonne. La valeur cumulative multiMatchBehavior spécifiée plus tôt pour le proxy devient pertinente maintenant, ce qui fait que les valeurs des douze mois de chaque année sont additionnées en une seule barre.

Pour n'afficher qu'un sous-ensemble d'années, réglez autoRowCategories sur false pour l'élément ItemModelBarDataProxy et définissez explicitement les catégories de ligne. De cette façon, seuls les éléments des catégories de ligne spécifiées sont visualisés.

Le troisième bloc intéressant montre comment obtenir l'index de ligne et de colonne d'un élément si vous connaissez les valeurs de ligne et de colonne en utilisant les méthodes ItemModelBarDataProxy, rowCategoryIndex() et columnCategoryIndex():

var timestamp = graphData.model.get(mainview.currentRow).timestamp
var pattern = /(\d\d\d\d)-(\d\d)/
var matches = pattern.exec(timestamp)
var rowIndex = modelProxy.rowCategoryIndex(matches[1])
var colIndex

if (barGraph.columnAxis == graphAxes.total)
    colIndex = 0 // Just one column when showing yearly totals
else
    colIndex = modelProxy.columnCategoryIndex(matches[2])

if (selectedSeries.visible)
    mainview.selectedSeries.selectedBar = Qt.point(rowIndex, colIndex)
else if (barSeries.visible)
    barSeries.selectedBar = Qt.point(rowIndex, colIndex)
else
    secondarySeries.selectedBar = Qt.point(rowIndex, colIndex)

Exemple de projet @ code.qt.io

© 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.