- Qt 6.6
- Qt Graphs
- Simple Scatter Graph
- Qt Graphs | Commercial or GPLv3

# Simple Scatter Graph

     // Copyright (C) 2023 The Qt Company Ltd.
     // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

     import QtQuick
     import QtQuick.Controls
     import QtGraphs

     Item {
         id: mainView
         width: 1600
         height: 1200

         property bool portraitMode: width < height
         // Adjust the button width based on screen orientation:
         // If we're in portrait mode, just fit two buttons side-by-side, otherwise
         // fit all of the buttons side-by-side.
         property real buttonWidth: mainView.portraitMode ? (mainView.width / 2 - 8)
                                                          : (mainView.width / 6 - 6)

         Data {
             id: seriesData
         }

         Theme3D {
             id: themeQt
             type: Theme3D.ThemeQt
             font.pointSize: 40
         }

         Theme3D {
             id: themeRetro
             type: Theme3D.ThemeRetro
         }

         Item {
             id: dataView
             anchors.bottom: parent.bottom
             width: parent.width
             // Adjust the space based on screen orientation:
             // If we're in portrait mode, we have 3 rows of buttons, otherwise they are all in one row.
             height: parent.height - (mainView.portraitMode ? shadowToggle.implicitHeight * 3 + 25
                                                            : shadowToggle.implicitHeight + 10)

             Scatter3D {
                 id: scatterGraph
                 anchors.fill: parent
                 theme: themeQt
                 shadowQuality: AbstractGraph3D.ShadowQualityHigh
                 scene.activeCamera.cameraPreset: Camera3D.CameraPresetFront
                 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"
                 Scatter3DSeries {
                     id: scatterSeries
                     itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel"

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

                 Scatter3DSeries {
                     id: scatterSeriesTwo
                     itemLabelFormat: "Series 2: X:@xLabel Y:@yLabel Z:@zLabel"
                     itemSize: 0.05
                     mesh: Abstract3DSeries.MeshCube

                     ItemModelScatterDataProxy {
                         itemModel: seriesData.modelTwo
                         xPosRole: "xPos"
                         yPosRole: "yPos"
                         zPosRole: "zPos"
                     }
                 }
                 Scatter3DSeries {
                     id: scatterSeriesThree
                     itemLabelFormat: "Series 3: X:@xLabel Y:@yLabel Z:@zLabel"
                     itemSize: 0.1
                     mesh: Abstract3DSeries.MeshMinimal

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

         Button {
             id: shadowToggle
             width: mainView.buttonWidth // Calculated elsewhere based on screen orientation
             anchors.left: parent.left
             anchors.top: parent.top
             anchors.margins: 5
             text: "Hide Shadows"
             onClicked: {
                 if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
                     scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityHigh;
                     text = "Hide Shadows";
                 } else {
                     scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
                     text = "Show Shadows";
                 }
             }
         }

         Button {
             id: smoothToggle
             width: mainView.buttonWidth
             anchors.left: shadowToggle.right
             anchors.top: parent.top
             anchors.margins: 5
             text: "Use Smooth for Series One"
             onClicked: {
                 if (!scatterSeries.meshSmooth) {
                     text = "Use Flat for Series One";
                     scatterSeries.meshSmooth = true;
                 } else {
                     text = "Use Smooth for Series One";
                     scatterSeries.meshSmooth = false;
                 }
             }
         }

         Button {
             id: cameraToggle
             width: mainView.buttonWidth
             anchors.left: mainView.portraitMode ? parent.left : smoothToggle.right
             anchors.top: mainView.portraitMode ? smoothToggle.bottom : parent.top
             anchors.margins: 5
             text: "Change Camera Placement"
             onClicked: {
                 if (scatterGraph.scene.activeCamera.cameraPreset === Camera3D.CameraPresetFront) {
                     scatterGraph.scene.activeCamera.cameraPreset =
                             Camera3D.CameraPresetIsometricRightHigh;
                 } else {
                     scatterGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetFront;
                 }
             }
         }

         Button {
             id: themeToggle
             width: mainView.buttonWidth
             anchors.left: cameraToggle.right
             anchors.top: mainView.portraitMode ? smoothToggle.bottom : parent.top
             anchors.margins: 5
             text: "Change Theme"
             onClicked: {
                 if (scatterGraph.theme.type === Theme3D.ThemeRetro)
                     scatterGraph.theme = themeQt;
                 else
                     scatterGraph.theme = themeRetro;
                 if (scatterGraph.theme.backgroundEnabled)
                     backgroundToggle.text = "Hide Background";
                 else
                     backgroundToggle.text = "Show Background";
             }
         }

         Button {
             id: backgroundToggle
             width: mainView.buttonWidth
             anchors.left: mainView.portraitMode ? parent.left : themeToggle.right
             anchors.top: mainView.portraitMode ? themeToggle.bottom : parent.top
             anchors.margins: 5
             text: "Hide Background"
             onClicked: {
                 if (scatterGraph.theme.backgroundEnabled) {
                     scatterGraph.theme.backgroundEnabled = false;
                     text = "Show Background";
                 } else {
                     scatterGraph.theme.backgroundEnabled = true;
                     text = "Hide Background";
                 }
             }
         }

         Button {
             id: exitButton
             width: mainView.buttonWidth
             anchors.left: backgroundToggle.right
             anchors.top: mainView.portraitMode ? themeToggle.bottom : parent.top
             anchors.margins: 5
             text: "Quit"
             onClicked: Qt.quit();
         }
     }