Einfaches Balkendiagramm

Verwendung von Bars3D in einer QML-Anwendung.

Simple Bar Graph zeigt, wie man mit Bars3D und QML ein einfaches 3D-Balkendiagramm erstellt.

In den folgenden Abschnitten wird beschrieben, wie Sie Serien umschalten und mehr als eine Serie gleichzeitig anzeigen können. Weitere Informationen zur grundlegenden Funktionalität von QML-Anwendungen finden Sie unter Einfaches Streudiagramm.

Ausführen des Beispiels

Zum Ausführen des Beispiels von Qt Creatorzu starten, öffnen Sie den Modus Welcome und wählen Sie das Beispiel unter Examples aus. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.

Daten

Der Beispieldatensatz besteht aus den monatlichen Einnahmen und Ausgaben eines fiktiven Unternehmens über mehrere Jahre. Die Daten sind in einem Listenmodell in Data.qml wie folgt definiert:

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" }
    ...

Jedes Datenelement hat drei Rollen: Zeitstempel, Einnahmen und Ausgaben. Der Zeitstempelwert hat das Format: <four digit year>-<two digit month>. Normalerweise würden Sie Jahre und Monate den Zeilen und Spalten eines Balkendiagramms zuordnen, aber Sie können nur entweder Einnahmen oder Ausgaben als Wert anzeigen.

Fügen Sie nun die Daten in das Diagramm Bars3D ein. Erstellen Sie darin zwei Bar3DSeries, beginnend mit einer Reihe für die Einnahmen:

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

Die Daten werden an die Eigenschaft itemModel der ItemModelBarDataProxy innerhalb der Reihe angehängt. Für valueRole geben Sie das Feld income an, da es den gewünschten Wert enthält. Die Ermittlung der Jahre und Monate ist etwas komplizierter, da sie sich beide im selben Feld befinden. Um diese Werte zu extrahieren, geben Sie das Feld timestamp sowohl für rowRole als auch für columnRole an. Zusätzlich geben Sie ein Suchmuster und eine Ersetzungsregel für diese Rollen an, um den richtigen Teil des Feldinhalts für jede Rolle zu extrahieren. Das Suchmuster ist ein normaler regulärer JavaScript-Ausdruck, und die Ersetzungsregel gibt an, durch was der Feldinhalt, der mit dem regulären Ausdruck übereinstimmt, ersetzt wird. In diesem Fall wird der gesamte Feldinhalt nur durch das Jahr oder den Monat ersetzt, der die erste erfasste Teilzeichenkette für beide Zeilen und Spalten ist. Weitere Informationen über die Ersetzungsfunktion mit regulären Ausdrücken finden Sie in der Dokumentation der Funktion QString::replace(const QRegExp &rx, const QString &after).

Die Eigenschaft multiMatchBehavior gibt an, was zu tun ist, wenn mehrere Elementmodellelemente auf dieselbe Zeilen-/Spaltenkombination passen. In diesem Fall werden ihre Werte addiert. Diese Eigenschaft hat keine Auswirkungen, wenn Werte für jeden Monat angezeigt werden, da es in unserem Artikelmodell keine doppelten Monate gibt. Sie wird jedoch später relevant, wenn Sie die Jahressummen anzeigen möchten.

Fügen Sie dann eine weitere Reihe für die Ausgaben hinzu:

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

Das Modell enthält Ausgaben als negative Werte, aber sie könnten als positive Balken dargestellt werden, um einen einfachen Vergleich mit den Einnahmen zu ermöglichen. Verwenden Sie die valueRolePattern, um das Minuszeichen zu entfernen, und es muss keine Ersatzzeichenfolge angegeben werden, da die Standard-Ersatzzeichenfolge eine leere Zeichenfolge ist.

Verwenden Sie die Eigenschaft visible der Reihe, um die zweite Reihe vorerst auszublenden.

Benutzerdefinierte Achsenbeschriftungen

Axes.qml definiert die Kategoriebeschriftungen für die Spaltenachse neu, da die Daten Zahlen für Monate enthalten, die die Beschriftungen überladen würden:

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

Um die Achsenbeschriftungen bei niedrigen Kamerawinkeln besser lesbar zu machen, stellen Sie die automatische Drehung der Achsenbeschriftung ein.

Umschalten von Serien

Richten Sie unter main.qml das Diagramm und verschiedene UI-Elemente ein. Es gibt drei interessante Codeblöcke, die hier hervorzuheben sind. Der erste zeigt, wie man die visualisierten Daten zwischen Einnahmen, Ausgaben und beidem ändern kann, indem man einfach die Sichtbarkeit der beiden Reihen ändert:

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"
    }
}

Das Achsenbeschriftungsformat und die Formate der Elementauswahl werden so angepasst, dass das negative Vorzeichen für Ausgaben, die eigentlich als positive Werte aufgelöst wurden, korrekt angezeigt wird.

Im zweiten interessanten Block werden die visualisierten Daten durch Anpassung der Proxy-Eigenschaften geändert:

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"
    }
}

Um die Jahressummen anzuzeigen, werden die zwölf Monate eines jeden Jahres zu einem einzigen Balken zusammengefasst. Dies wird durch die Angabe einer columnRolePattern erreicht, die mit allen Modellelementen übereinstimmt. Auf diese Weise wird die Reihe nur eine einzige Spalte haben. Die zuvor für den Proxy angegebene kumulative multiMatchBehavior wird jetzt relevant, da die Werte aller zwölf Monate jedes Jahres zu einem einzigen Balken addiert werden.

Um nur eine Untergruppe von Jahren anzuzeigen, setzen Sie autoRowCategories für das Element ItemModelBarDataProxy auf false und definieren Sie die Zeilenkategorien explizit. Auf diese Weise werden nur die Elemente in den angegebenen Zeilenkategorien angezeigt.

Der dritte interessante Block zeigt, wie man den Zeilen- und Spaltenindex eines Elements erhält, wenn man die Zeilen- und Spaltenwerte kennt, indem man die Methoden ItemModelBarDataProxy rowCategoryIndex() und columnCategoryIndex() verwendet:

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)

Beispielprojekt @ code.qt.io

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