Auf dieser Seite

Einfaches Streudiagramm

Verwendung von „ Scatter3D “ in einer QML-Anwendung.

„Einfaches Streudiagramm“ zeigt, wie man mithilfe von „ Scatter3D “ und QML eine einfache Streudiagramm-Visualisierung erstellt.

Anleitungen zur Interaktion mit dem Diagramm finden Sie auf dieser Seite.

Anleitungen zum Erstellen einer eigenen neuen „ Qt Quick “-Anwendung finden Sie in der Hilfe unter „ Qt Creator “.

3D-Streudiagramm mit farbigen Kugeln und Steuerelementen zur Visualisierung

Ausführen des Beispiels

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

Einrichten des Layouts

Bevor Sie sich mit dem QML-Code befassen, richtet „ main.cpp “ die Anwendung ein. Die Datei „ main.qml “ wird aus der Ressource (qrc:) eingelesen.

viewer.setSource(QUrl("qrc:/qml/scatter/main.qml"));

Diese Datei „ main.qml “ ist der Ausgangspunkt für den QML-Code der Anwendung. Importieren Sie zunächst alle erforderlichen QML-Module:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtGraphs

Erstellen Sie anschließend ein „ Data “-Element, das die Daten für das Diagramm enthält.

Data {
    id: seriesData
}

Erstellen Sie anschließend zwei „ GraphsTheme “-Elemente, die zwei verschiedene Designs für das Diagramm definieren: ein „Qt Green“-Design und ein „Qt Neon Green“-Design.

GraphsTheme {
    id: themeQt
    theme: GraphsTheme.Theme.QtGreen
    labelFont.pointSize: 40
}

GraphsTheme {
    id: themeQtNeonGreen
    theme: GraphsTheme.Theme.QtGreenNeon
    colorScheme: GraphsTheme.ColorScheme.Dark
}

Das Layout dieser Anwendung besteht aus fünf verschiedenen Schaltflächen zum Ein- und Ausschalten verschiedener visueller Optionen für das Diagramm sowie natürlich aus dem Diagramm selbst. Es gibt viele Möglichkeiten, diese anzuordnen. Eine Möglichkeit besteht darin, ein „ GridLayout “ zu verwenden, das vier Schaltflächen, das „ Graph “ und die fünfte Schaltfläche enthält, die alle in einem „ ColumnLayout “ angezeigt werden.

ColumnLayout {
    id: mainLayout
    anchors.fill: parent
    anchors.margins: margin
    spacing: spacing

Der „ GridLayout “ ist responsiv. Das bedeutet, dass die Anzahl der verwendeten Spalten von der Breite des Anwendungsfensters abhängt. Dies wird erreicht, indem der Eigenschaft „ columns “ ein ternärer Operator zugewiesen wird, der je nach Fensterbreite den Wert 1, 2 oder 4 annimmt.

GridLayout {
    Layout.fillWidth: true
    rowSpacing: spacing
    columnSpacing: spacing

    columns: mainView.width < mainView.buttonMinWidth * 2 + mainView.spacing + mainView.margin * 2 // width of 2 buttons
             ? 1
             : (mainView.width < mainView.buttonMinWidth * 4 + mainView.spacing * 3 + mainView.margin * 2 // width of 4 buttons
                ? 2
                : 4)

In diesem „ GridLayout “ werden vier „ RoundButton“-Instanzen erstellt: eine zum Ein- und Ausschalten von Schatten, eine zur Glättung des Gitters, eine für die Kameraposition und schließlich eine zum Ändern des Hintergrunds des Diagramms. Alle Schaltflächen folgen derselben Struktur. Anstatt diese Struktur für alle Schaltflächen neu zu definieren, kann eine benutzerdefinierte Komponente erstellt werden.

component CustomButton : RoundButton {
    id: buttonRoot

CustomButtom erweitert den Typ „ RoundButton “, fügt jedoch einige Ergänzungen hinzu. Es werden Eigenschaften wie „ Layout.minimumWidth “, „ Layout.FillWidth “, „ radius “ und „ background “ festgelegt. Diese definieren das Styling und das Layout der Schaltfläche.

property alias source: iconImage.source

Layout.minimumWidth: buttonMinWidth
Layout.fillWidth: true

radius: mainView.radius

background: Rectangle {
    radius: mainView.radius
    color: "white"
    border.color: "black"
}

Während die Eigenschaft „ contentItem “ den Inhalt der Schaltfläche definiert, handelt es sich in diesem Fall um einen „ Row “-Typ, der ein Symbol und etwas Text enthält. Das Symbol wird mithilfe eines „ Image “-Typs importiert, wobei die Eigenschaft „ source “ festgelegt wird. Der Text wird mithilfe eines „ Label “-Typs erstellt und über dessen Eigenschaft „ text “ festgelegt. Für diese beiden Eigenschaften werden am Anfang der benutzerdefinierten Komponente zwei Aliase erstellt, damit sie beim Erstellen einer Instanz von „ CustomButton “ festgelegt werden können.

contentItem: Row {
    id: content
    Image {
        id: iconImage
    }
    Label {
        text: buttonRoot.text
        horizontalAlignment: Text.AlignLeft
        anchors.verticalCenter: parent.verticalCenter
    }
}

In der Datei „ GridLayout “ werden vier „ CustomButton“-Objekte erstellt. Es müssen drei Eigenschaften festgelegt werden: die beiden Aliase für das Symbolbild und den Text sowie das Signal „ onClicked “.

CustomButton {
    id: shadowButton
    text: graph.shadowQuality === Graphs3D.ShadowQuality.None ?
              qsTr("Show Shadows") : qsTr("Hide Shadows")
    source: graph.shadowQuality === Graphs3D.ShadowQuality.None ?
                "qrc:/images/shadow.svg" : "qrc:/images/shadow_hide.svg"
    onClicked: {
        graph.shadowQuality = graph.shadowQuality === Graphs3D.ShadowQuality.None ?
                    Graphs3D.ShadowQuality.High :
                    Graphs3D.ShadowQuality.None
    }
}

Beispielsweise legt die Schaltfläche „Schatten“ das „ onClicked “-Zeichen so fest, dass der Schatten ein- und ausgeschaltet werden kann.

Einrichten des Diagramms

Als Nächstes folgt im Layout der „ Graph “; dieser ist in einer eigenen QML-Datei „ Graph.qml “ definiert und wird wie folgt instanziiert:

Graph {
    id: graph
    Layout.fillWidth: true
    Layout.fillHeight: true
}

Betrachtet man die Implementierung in „ Graph.qml “, so ist das Diagramm vom Typ „ Scatter3D “ und in einem Typ „ Item “ verschachtelt.

Scatter3D {
    id: scatterGraph

Vor der Definition der Datensätze werden einige der Achsen-Eigenschaften konfiguriert.

axisX.segmentCount: 3
axisX.subSegmentCount: 2
axisX.labelFormat: "%.2f"
axisZ.segmentCount: 2
axisZ.subSegmentCount: 2
axisZ.labelFormat: "%.2f"
axisY.segmentCount: 2
axisY.subSegmentCount: 2
axisY.labelFormat: "%.2f"

Einrichten der Daten

Das Diagramm zeigt drei Datensätze, die die in Data.qml angegebenen Daten darstellen. Die Datensätze werden in Objekten vom Typ „ ListModel “ gespeichert

ListModel {
    id: dataModel
    ListElement{ xPos: -10.0; yPos: 5.0; zPos: -5.0 }
    ...
    ListElement{ xPos: -7.54 ; yPos: 2.8 ; zPos: -3.68 }
}

ListModel {
    id: dataModelTwo
    ListElement{ xPos: 2.25 ; yPos: 1.36 ; zPos: -1.3 }
    ...
    ListElement{ xPos: -3.4 ; yPos: 0.6 ; zPos: 0.9 }
}

ListModel {
    id: dataModelThree
    ListElement{ xPos: 8.0; yPos: -2.0; zPos: 4.0 }
    ...
    ListElement{ xPos: 5.66 ; yPos: -4.98 ; zPos: 3.72 }
}

und werden den anderen Dateien über ` property aliases` zur Verfügung gestellt

property alias model: dataModel
property alias modelTwo: dataModelTwo
property alias modelThree: dataModelThree

Bevor diese Aliase verwendet werden, erstellen Sie einen Typ „ Scatter3DSeries “, der ein Element vom Typ „ ItemModelScatterDataProxy “ enthält.

Scatter3DSeries {
    id: scatterSeries
    itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel"

    ItemModelScatterDataProxy {
        itemModel: seriesData.model
        xPosRole: "xPos"
        yPosRole: "yPos"
        zPosRole: "zPos"
    }
}

Dieser Datenproxy verweist über seine Eigenschaft „ itemModel “ auf die Datensätze in „ Data.qml “. Der Zugriff auf die oben genannten Aliase erfolgt über die Eigenschaft „ id “ des Typs „ Data “, der in „ main.qml “ und „ seriesData “ instanziiert wurde.

itemModel: seriesData.model

Wiederholen Sie diesen Vorgang für die beiden verbleibenden Datensätze.

Scatter3DSeries {
    id: scatterSeriesTwo
    ...
ItemModelScatterDataProxy {
    itemModel: seriesData.modelTwo
    ...
    }
}
Scatter3DSeries {
    id: scatterSeriesThree
    ...
ItemModelScatterDataProxy {
    itemModel: seriesData.modelThree
    ...
    }
}

Großartig, das Streudiagramm verweist nun auf die drei Datensätze.

Jetzt müssen wir nur noch die verbleibende Schaltfläche, „ theme button “, zu unserem „ ColumnLayout “ hinzufügen. Der einzige Unterschied bei dieser Schaltfläche besteht darin, dass sie auf der linken Seite des Layouts positioniert ist. Dies wird festgelegt, indem die Eigenschaft „ Layout.alignment “ auf „ Qt.AlignLeft “ und „ Layout.fillWidth “ auf „ false “ gesetzt wird.

CustomButton {
    id: themeButton
    Layout.alignment: Qt.AlignLeft
    Layout.fillWidth: false

Beispielinhalt

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.