Sur cette page

Graphique à barres simple

Utilisation d'Bars3D dans une application QML.

La section «Graphique à barres simple » explique comment créer un graphique à barres 3D simple à l'aide d'Bars3D et de QML.

Diagrammes à barres en 3D présentant les données relatives aux dépenses et aux recettes sur plusieurs années

Les sections suivantes décrivent comment changer de série et afficher plusieurs séries à la fois. Pour plus d’informations sur les fonctionnalités de base des applications QML, consultez la section « Graphique de dispersion simple ».

Exécution de l'exemple

Vous pouvez exécuter l'exemple à partir de :

Données

L'ensemble de données d'exemple correspond aux revenus et dépenses mensuels d'une entreprise fictive sur plusieurs années. Les données sont définies dans un modèle de liste dans Data.qml comme suit :

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 comporte trois rôles : horodatage, recettes et dépenses. La valeur d’horodatage est au format : <four digit year>-<two digit month>. En général, vous associez les années et les mois aux lignes et aux colonnes d’un graphique à barres, mais vous ne pouvez afficher que les recettes ou les dépenses comme valeur.

Ajoutez maintenant les données au graphique Bars3D. Créez deux Bar3DSeries à l’intérieur, 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 associées à la propriété « itemModel » de l’ ItemModelBarDataProxy au sein de la série. Pour l’ valueRole, spécifiez le champ « income » car il contient la valeur souhaitée. L’extraction des années et des mois est un peu plus compliquée, car ils se trouvent tous deux dans le même champ. Pour extraire ces valeurs, spécifiez le champ « timestamp » à la fois pour « rowRole » et « columnRole ». De plus, définissez un motif de recherche et une règle de remplacement pour ces rôles afin d’extraire la partie appropriée du contenu du champ pour chaque rôle. Le motif de recherche est une expression régulière JavaScript standard, 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, remplacez l’intégralité du contenu du champ par l’année ou le mois uniquement, qui constituent la première sous-chaîne capturée tant pour les lignes que pour les colonnes. Pour plus d’informations sur la fonctionnalité de remplacement avec des expressions régulières, consultez la documentation de la fonction ` QString::replace(const QRegExp &rx, const QString &after)`.

La propriété « multiMatchBehavior » spécifie la marche à suivre lorsque plusieurs éléments du modèle d’éléments correspondent à la même combinaison ligne/colonne. Dans ce cas, additionnez leurs valeurs. Cette propriété n’a aucun effet lors de l’affichage des valeurs mensuelles, car il n’y a pas de mois en double dans notre modèle d’éléments. Elle devient toutefois pertinente par la suite, 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 les dépenses sous forme de valeurs négatives, mais celles-ci pourraient être affichées sous forme de barres positives pour faciliter la comparaison avec les barres de revenus. Utilisez la propriété ` valueRolePattern ` pour supprimer le signe moins ; il n’est pas nécessaire de spécifier de chaîne de remplacement, car la valeur 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éfinissez les libellés de catégorie de l’axe des colonnes, car les données contiennent des nombres correspondant aux mois, ce qui encombrerait les libellés :

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 vue est faible, activez la rotation automatique des étiquettes d’axe.

Changement de série

Dans ` main.qml`, configurez le graphique et divers éléments de l’interface utilisateur. Trois blocs de code intéressants méritent d’être soulignés ici. Le premier montre comment basculer entre l’affichage des revenus, des dépenses ou des deux, en modifiant 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 des étiquettes d’axe et celui des étiquettes de sélection des éléments ont été ajustés pour que le signe négatif s’affiche correctement pour les dépenses, qui avaient en réalité été interprétées 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, regroupez les douze mois de chaque année en un seul histogramme. Pour ce faire, spécifiez une valeur « columnRolePattern » qui corresponde à tous les éléments du modèle. De cette manière, la série ne comportera qu’une seule colonne. L’ multiMatchBehavior e cumulatif spécifié précédemment pour le proxy entre alors en jeu, ce qui entraîne l’addition des valeurs des douze mois de chaque année en un seul histogramme.

Pour n’afficher qu’un sous-ensemble d’années, définissez l’ autoRowCategories sur « false » pour l’élément « ItemModelBarDataProxy » et définissez explicitement les catégories de lignes. De cette manière, seuls les éléments appartenant aux catégories de lignes 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, à l’aide des 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.