Wind Turbine Dashboard
A wind turbine dashboard with 2D and 3D graphs.
The Wind Turbine Dashboard example demonstrates how to use both 2D and 3D graphs in a simulated real-world application.

Running the Example
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, see Qt Creator: Tutorial: Build and run.
Overview of the Application
The example demonstrates a wind turbine monitoring dashboard, referred to as the Aerospace Hub, which displays simulated data from an imaginary wind turbine field. A variety of graph types are employed to visualize different kinds of data. For example, a 2D graph with a spline series illustrates hourly power output, while an accompanying area series represents the accumulated power over the same period. Multiple data views are available, allowing users to explore and analyze the information from different perspectives.
The main interface features a settings toolbar on the left. Depending on the selected mode, the layout may include a status pane, a dashboard of smaller graphs, a primary large graph, or a detailed settings panel - either individually or in combination. This flexible design enables users to customize their view and focus on the most relevant data for their current analysis.
Dashboard View
The dashboard view presents the current system status alongside a scrollable pane that displays miniature previews of the various graphs. Up to four graphs are shown simultaneously, allowing users to conveniently browse through all six available visualizations and quickly assess key performance metrics at a glance.

Detail View
The detail view, accessible by selecting a miniature graph from the dashboard, enables users to examine the chosen visualization in greater depth and at a larger scale. Depending on the graph type, users can zoom, pan, or rotate the view to explore the data interactively. Additionally, individual data points can be hovered over or clicked to reveal more detailed information about the specific item of interest.

Settings View
The settings view, accessible by clicking either the settings button in the toolbar or in a miniature graph, allows users to adjust the visual theme of the graphs and modify settings specific to each graph type. Certain configurations persist after exiting the settings view, while others apply only within the current view, providing flexibility for both temporary and permanent adjustments.

Implementation Details
Everything in the application has been designed in a modular fashion. Main view, which is the Main.qml file, is an ApplicationWindow, which instantiaties the data simulators for each graph, as well as the root Item holding all of the UI elements.
The FontLoader is used for applying a global font for the whole UI.
ApplicationWindow {
...
FontLoader { ... }
font.family: interFont.name
// Data simulators
PieSimulator {
id: piesim
...
}
BarSimulator {
id: barsim
...
}
LineSimulator {
id: linesim
...
}
Data3DSimulator {
id: barDataSimulator
...
}
Data3DSimulator {
id: scatterDataSimulator
...
}
Data3DSimulator {
id: surfaceDataSimulator
...
}
// Root item
Item {...}
}The root item holds the background graphics and a Layout handling the placement of each UI element in the view:
// Background image Image { anchors.fill: parent source: root.state === "ShowSettings" ? "images/settings-bg.png" : "images/dashboard-bg.png" fillMode: Image.PreserveAspectCrop } // Everything except background image ColumnLayout { anchors.fill: parent ...
Most of the elements have been taken out of the Main.qml file itself into their own QML components to be used in the layouts, like the ToolBarItem in the snippet below:
// Vertical toolbar ToolBarItem { Layout.preferredWidth: GlobalSettings.toolbarwidth Layout.fillHeight: true } // Everything except vertical toolbar, header, and background image ColumnLayout { id: maincontentview Layout.fillWidth: true Layout.fillHeight: true ...
Transitions between different view is handled using states and transitions:
states: [ State { name: "ShowDashboard" }, State { name: "ShowSettings" PropertyChanges { maincontent.opacity: 0 settingscontent.opacity: 1 } PropertyChanges { viewtextdesc.text: "/ Settings" } }, ... // Use transitions to bring the selected view to the front transitions: [ Transition { NumberAnimation { properties: "opacity" easing.type: Easing.InOutCubic duration: 1000 } } ]
Dashboard
Dashboard is a part of the main content, another RowLayout inside the Layout hierarchy:
// Main content RowLayout { id: maincontent Layout.fillWidth: true Layout.fillHeight: true ...
It is made up of a status pane and a dashboard pane:
// Status area; turbine image, notification, status texts, and turbine name StatusPane { id: statuspane Layout.preferredWidth: GlobalSettings.statusimagewidth Layout.fillHeight: true } // Scrollable dashboard graph area, shown when in ShowDashboard state DashboardPane { id: dashboardpane contentheight: statuspane.height * 1.5 Layout.preferredWidth: GlobalSettings.dashboardwidth Layout.fillHeight: true }
Status Pane
Status pane has also been made up of smaller elements, implemented in their own QML components:
// Masking the turbine image of the background image ImageItem { anchors.fill: parent } // Notification NotificationItem { anchors.top: turbineimage.top anchors.horizontalCenter: turbineimage.horizontalCenter anchors.topMargin: GlobalSettings.doublespacing width: turbineimage.width / 1.25 } // Status StatusItem { anchors.centerIn: turbineimage width: turbineimage.width / 1.5 height: turbineimage.width / 1.75 } // Turbine name Label { ...
The implementation of these is not relevant, so that part will be skipped.
Dashboard Pane
Dashboard is the element holding the six small graph previews. Only four of those are visible at a time, so they have to be added inside an element that can be scrolled. In this case, it is done with a Flickable, which holds a GridLayout:
Flickable { property alias contentheight: content.height clip: true contentHeight: contentheight boundsBehavior: Flickable.StopAtBounds interactive: true visible: opacity > 0.5 Item { id: content width: parent.width GridLayout { id: grid columns: 2 ...
The graph previews are added inside the grid layout, and like most other elements, they have been implemented inside their own elements:
// Graph 1: Power output over time SmallGraphItem { Layout.fillWidth: true Layout.fillHeight: true state: "Area2D" linesimulator: linesim } // Graph 2: Energy production x Turbine SmallGraphItem { Layout.fillWidth: true Layout.fillHeight: true state: "Bar2D" barsimulator: barsim } ...
The SmallGraphItem element is a generic one, holding all different graph types inside it, and the required type is given to it as a state.
SmallGraphItem has:
- A header element
- An instance of each graph type, for which visibility is set to false by default using an opacity trigger
- A rectangle to darken the preview
- A mouse area to handle hover and mouse clicks on the preview
Pie2DGraph { id: pie2d anchors.topMargin: header.height + GlobalSettings.defaultspacing anchors.rightMargin: GlobalSettings.defaultspacing anchors.fill: parent opacity: 0 piesimulator: smallgraph.piesimulator } Bar3DGraph { id: bar3d anchors.topMargin: header.height + GlobalSettings.defaultspacing anchors.bottomMargin: GlobalSettings.defaultspacing anchors.fill: parent opacity: 0 cameraZoomLevel: GlobalSettings.defaultzoom cameraPreset: GlobalSettings.defaultpreset } ...
Opacities are used for transition animations, which is why they have been set to 0 in the previews by default. When opacity is animated above 0.5, the preview graph itself is set visible:
Bars3D { id: graph visible: opacity > 0.5 ...
Details
Details is also a part of the main content, using the same RowLayout inside the Layout hierarchy. It is made up of the same status pane as the Dashboard, and a details pane:
// Details graph, shown when in correct state BigGraphItem { id: detailspane Layout.preferredWidth: GlobalSettings.dashboardwidth Layout.fillHeight: true state: root.state radius: GlobalSettings.defaultradius piesimulator: piesim barsimulator: barsim linesimulator: linesim detailsview: true }
The details pane, BigGraphItem, is similar to the SmallGraphItem in a sense that it also holds an instance of each graph in it, in addition to other elements:
// Graphs Area2DGraph { id: area2dbig Layout.fillWidth: true Layout.fillHeight: true Layout.margins: GlobalSettings.defaultmargin opacity: 0 panStyle: GraphsView.PanStyle.Drag zoomStyle: GraphsView.ZoomStyle.Center linesimulator: biggraph.linesimulator onVisibleChanged: { if (visible) biggraph.activegraph = area2dbig } } Bar2DGraph { id: bar2dbig Layout.fillWidth: true Layout.fillHeight: true Layout.margins: GlobalSettings.defaultmargin opacity: 0 panStyle: GraphsView.PanStyle.Drag zoomStyle: GraphsView.ZoomStyle.Center barsimulator: biggraph.barsimulator onVisibleChanged: { if (visible) biggraph.activegraph = bar2dbig } } ...
Other elements included are a dropdown combobox for selecting the graph type, control buttons for rotating, panning, and zooming - depending on the graph type - and a tooltip for the buttons. Like SmallGraphItem, the graph type shown is decided based on the state.
Settings
Settings has been taken outside the main content Layout, as it is not using any parts of the Dashboard or Details views:
// Settings SettingsItem { id: settingscontent anchors.fill: parent ...
Settings view holds another BigGraphItem for displaying the graph, and a settings pane for adjusting either the GraphsTheme properties or some properties sepcific to the selected graph type.
// Graph detail BigGraphItem { id: settingsgraph width: GlobalSettings.settingsgraphwidth anchors.top: parent.top anchors.bottom: parent.bottom anchors.topMargin: GlobalSettings.graphdetailmargin radius: GlobalSettings.defaultradius opacity: parent.opacity piesimulator: settingsitem.piesimulator barsimulator: settingsitem.barsimulator linesimulator: settingsitem.linesimulator } // Settings pane StackLayout { id: settingspane ...
Global Theme
The settings on the General Settings tab affect all graphs in the application. A global GraphsTheme has been implemented as a Singleton in GlobalSettings.qml:
pragma Singleton ... QtObject { id: global ... // Common graph theme property var theme: GraphsTheme { plotAreaBackgroundVisible: false backgroundVisible: false colorScheme: GraphsTheme.ColorScheme.Dark theme: GraphsTheme.Theme.BlueSeries labelTextColor: "#AEAEAE" labelBackgroundVisible: true labelFont.pointSize: global.fontsize28px grid.mainColor: "#AEAEAE" grid.mainWidth: 1 baseGradients: [ global.customgradient ] }
This global shared theme is set to each graph as the theme:
theme: GlobalSettings.theme
As a singleton, the GlobalSettings.qml needs to be tagged as one in the CMakeLists.txt as well, to be usable in the application:
set_source_files_properties(qml/GlobalSettings.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
Graph Settings
The settings in the Graph Settings tab only affect the currently selected graph. These settings do not change the global theme, but the series in the active graph only.
© 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.