Qt Quick 2 Surface Multiseries Example
Using multiple series with Surface3D in a QML application.
The Qt Quick 2 surface example shows how to make a 3D surface plot displaying 3 layers using Surface3D with Qt Quick 2.
The focus in this example is on generating a multiseries surface plot from 3 different height map images, so in this section we skip explaining the application creation. For a more detailed QML example documentation, see Qt Quick 2 Scatter Example.
Running the Example
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.
Adding Data to the Graph
This example shows how to add several surface series to one graph using using HeightMapSurfaceDataProxies and how to control their visibilities individually.
Let's start by creating a specific gradient for each layer:
ColorGradient { id: layerOneGradient ColorGradientStop { position: 0.0; color: "black" } ColorGradientStop { position: 0.31; color: "tan" } ColorGradientStop { position: 0.32; color: "green" } ColorGradientStop { position: 0.40; color: "darkslategray" } ColorGradientStop { position: 1.0; color: "white" } } ColorGradient { id: layerTwoGradient ColorGradientStop { position: 0.315; color: "blue" } ColorGradientStop { position: 0.33; color: "white" } } ColorGradient { id: layerThreeGradient ColorGradientStop { position: 0.0; color: "red" } ColorGradientStop { position: 0.15; color: "black" } }
Then we'll create the series themselves. It happens simply by adding 3 separate Surface3DSeries to the Surface3D graph as children:
... Surface3DSeries { id: layerOneSeries baseGradient: layerOneGradient HeightMapSurfaceDataProxy { heightMapFile: ":/heightmaps/layer_1.png" } flatShadingEnabled: false drawMode: Surface3DSeries.DrawSurface visible: layerOneToggle.checked // bind to checkbox state } Surface3DSeries { id: layerTwoSeries baseGradient: layerTwoGradient HeightMapSurfaceDataProxy { heightMapFile: ":/heightmaps/layer_2.png" } flatShadingEnabled: false drawMode: Surface3DSeries.DrawSurface visible: layerTwoToggle.checked // bind to checkbox state } Surface3DSeries { id: layerThreeSeries baseGradient: layerThreeGradient HeightMapSurfaceDataProxy { heightMapFile: ":/heightmaps/layer_3.png" } flatShadingEnabled: false drawMode: Surface3DSeries.DrawSurface visible: layerThreeToggle.checked // bind to checkbox state } ...
You'll notice we added the created gradients to the baseGradient
properties of the series. We could have added them to the baseGradients
property of the Theme3D in Surface3D instead, but doing it this way ensures each gradient is applied to a correct series:
Surface3DSeries { id: layerOneSeries baseGradient: layerOneGradient ...
Controlling the Graph
Let's add some checkboxes to control the visibility of layers:
GroupBox { flat: true Layout.fillWidth: true Column { spacing: 10 Label { font.pointSize: fontSize font.bold: true text: "Layer Selection" } CheckBox { id: layerOneToggle checked: true style: CheckBoxStyle { label: Label { font.pointSize: fontSize text: "Show Ground Layer" } } } CheckBox { id: layerTwoToggle checked: true style: CheckBoxStyle { label: Label { font.pointSize: fontSize text: "Show Sea Layer" } } } CheckBox { id: layerThreeToggle checked: true style: CheckBoxStyle { label: Label { font.pointSize: fontSize text: "Show Tectonic Layer" } } } } }
We don't need to do anything on the onCheckedChanged
as we bound the checked
state to the visible
property of the series directly:
... visible: layerOneToggle.checked // bind to checkbox state ...
Let's add some more checkboxes to control how the layers are displayed, when visible:
GroupBox { flat: true Layout.fillWidth: true Column { spacing: 10 Label { font.pointSize: fontSize font.bold: true text: "Layer Style" } CheckBox { id: layerOneGrid style: CheckBoxStyle { label: Label { font.pointSize: fontSize text: "Show Ground as Grid" } } onCheckedChanged: { if (checked) layerOneSeries.drawMode = Surface3DSeries.DrawWireframe else layerOneSeries.drawMode = Surface3DSeries.DrawSurface } } CheckBox { id: layerTwoGrid style: CheckBoxStyle { label: Label { font.pointSize: fontSize text: "Show Sea as Grid" } } onCheckedChanged: { if (checked) layerTwoSeries.drawMode = Surface3DSeries.DrawWireframe else layerTwoSeries.drawMode = Surface3DSeries.DrawSurface } } CheckBox { id: layerThreeGrid style: CheckBoxStyle { label: Label { font.pointSize: fontSize text: "Show Tectonic as Grid" } } onCheckedChanged: { if (checked) layerThreeSeries.drawMode = Surface3DSeries.DrawWireframe else layerThreeSeries.drawMode = Surface3DSeries.DrawSurface } } } }
In addition to these we have three buttons, one of which is of special interest to us. It is used to control whether we want to slice into only one layer, or all of them:
NewButton { id: sliceButton text: "Slice All Layers" fontSize: fontSize Layout.fillWidth: true Layout.minimumHeight: 40 onClicked: { if (surfaceLayers.selectionMode & AbstractGraph3D.SelectionMultiSeries) { surfaceLayers.selectionMode = AbstractGraph3D.SelectionRow | AbstractGraph3D.SelectionSlice text = "Slice All Layers" } else { surfaceLayers.selectionMode = AbstractGraph3D.SelectionRow | AbstractGraph3D.SelectionSlice | AbstractGraph3D.SelectionMultiSeries text = "Slice One Layer" } } }