Auf dieser Seite

Einfaches Balkendiagramm

Verwendung von Bars3D in einer QML-Anwendung.

„Einfaches Balkendiagramm“ zeigt, wie man mit Bars3D und QML ein einfaches 3D-Balkendiagramm erstellt.

3D-Balkendiagramm zum Vergleich der monatlichen Einnahmen und Ausgaben über mehrere Jahre hinweg

In den folgenden Abschnitten wird beschrieben, wie man zwischen Reihen wechselt und mehrere Reihen gleichzeitig anzeigt. Weitere Informationen zu den grundlegenden Funktionen von QML-Anwendungen finden Sie unter „Einfaches Streudiagramm“.

Ausführen des Beispiels

Sie können das Beispiel wie folgt ausführen:

Daten

Der Beispieldatensatz umfasst die monatlichen Einnahmen und Ausgaben eines fiktiven Unternehmens über mehrere Jahre hinweg. 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" }
    ...

Jeder Datensatz 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 als Wert können Sie nur entweder Einnahmen oder Ausgaben anzeigen.

Fügen Sie nun die Daten dem „Bars3D“-Diagramm hinzu. 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.MMBCumulative
    }
    ...

Die Daten werden der Eigenschaft „ itemModel “ des „ItemModelBarDataProxy“ innerhalb der Serie zugewiesen. Für „ valueRole “ geben Sie das Feld „ income “ an, da es den gewünschten Wert enthält. Das Abrufen der Jahre und Monate ist etwas komplizierter, da beide im selben Feld enthalten sind. Um diese Werte zu extrahieren, geben Sie sowohl für „ rowRole “ als auch für „ columnRole “ das Feld „ timestamp “ an und legen Sie zusätzlich ein Suchmuster sowie eine Ersetzungsregel für diese Rollen fest, um den richtigen Teil des Feldinhalts für jede Rolle zu extrahieren. Das Suchmuster ist ein normaler regulärer Ausdruck in JavaScript, und die Ersetzungsregel legt fest, durch welchen Inhalt der Feldinhalt ersetzt wird, der dem regulären Ausdruck entspricht. In diesem Fall wird der gesamte Feldinhalt durch das Jahr oder den Monat ersetzt – also durch die erste erfasste Teilzeichenfolge sowohl für Zeilen als auch für Spalten. Weitere Informationen zur Ersetzungsfunktion mit regulären Ausdrücken finden Sie in der Funktionsdokumentation zu ` QString::replace` (`const QRegExp &rx, const QString &after)`.

Die Eigenschaft „ multiMatchBehavior “ legt fest, was zu tun ist, wenn mehrere Elemente des Elementmodells mit derselben Zeilen-/Spaltenkombination übereinstimmen. In diesem Fall werden ihre Werte addiert. Diese Eigenschaft hat keine Auswirkung, wenn Werte für jeden Monat angezeigt werden, da es in unserem Elementmodell keine doppelten Monate gibt, wird jedoch später relevant, wenn Sie die Jahressummen anzeigen möchten.

Fügen Sie anschließend 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.MMBCumulative
    }
    ...

Das Modell enthält Ausgaben als negative Werte, Sie möchten diese jedoch als positive Balken anzeigen, damit sie leicht mit den Einkommensbalken verglichen werden können. Verwenden Sie dazu die Eigenschaft „ valueRolePattern “, um das Minuszeichen zu entfernen. Es muss keine Ersatzzeichenfolge angegeben werden, da die Standardersetzung 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 Säulenachse neu, da die Daten Zahlen für Monate enthalten, die die Beschriftungen unübersichtlich machen würden:

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

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

Wechseln zwischen Reihen

Richten Sie unter „ main.qml “ das Diagramm und verschiedene UI-Elemente ein. Hier sind drei interessante Codeblöcke hervorzuheben. Der erste zeigt, wie Sie die visualisierten Daten zwischen Einnahmen, Ausgaben und beidem wechseln können, indem Sie einfach die Sichtbarkeit der beiden Reihen ändern:

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 Format der Achsenbeschriftungen und der Elementauswahlbeschriftungen wurde angepasst, damit das Minuszeichen bei den Ausgaben korrekt angezeigt wird, die tatsächlich als positive Werte ausgewertet wurden.

Der zweite interessante Block ist der, in dem die visualisierten Daten durch Anpassen der Proxy-Eigenschaften geändert werden:

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 jedes Jahres zu einem einzigen Balken zusammengefasst. Dies wird erreicht, indem ein „ columnRolePattern “ angegeben wird, das mit allen Modellelementen übereinstimmt. Auf diese Weise verfügt der Daten-Proxy nur über eine einzige Spalte. Der zuvor für den Proxy festgelegte kumulative „ multiMatchBehavior “ kommt nun zum Tragen und bewirkt, dass die Werte aller zwölf Monate jedes Jahres zu einem einzigen Balken addiert werden.

Um nur eine Teilmenge von Jahren anzuzeigen, setzen Sie die Eigenschaft „ autoRowCategories “ des Elements „ItemModelBarDataProxy“ auf „false“ und definieren Sie die Zeilenkategorien explizit. Auf diese Weise werden nur die Elemente in den angegebenen Zeilenkategorien visualisiert.

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

onCurrentRowChanged: {
    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

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