Gráfico de dispersión simple
Utilizando Scatter3D en una aplicación QML.
Simple Scatter Graph muestra cómo realizar una visualización sencilla de un gráfico de dispersión utilizando Scatter3D y QML.
Para obtener instrucciones sobre cómo interactuar con el gráfico, consulte esta página.
Para obtener instrucciones sobre cómo crear una nueva aplicación Qt Quick propia, consulte la ayuda de Qt Creator.

Ejecutar el ejemplo
Para ejecutar el ejemplo desde Qt Creator, abra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.
Configuración del diseño
Antes de sumergirse en el código QML, main.cpp configura la aplicación. El archivo main.qml se lee del recurso (qrc:)
viewer.setSource(QUrl("qrc:/qml/scatter/main.qml"));
Este archivo main.qml es el punto de partida para el código QML de la aplicación. En primer lugar, importa todos los módulos QML necesarios:
import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtGraphs
A continuación, cree un elemento Data que será el elemento que contenga los datos para el gráfico.
Data { id: seriesData }
A continuación, crea dos elementos GraphsTheme que definan dos temas diferentes para el gráfico, un tema Qt Green y un tema Qt Neon Green.
GraphsTheme { id: themeQt theme: GraphsTheme.Theme.QtGreen labelFont.pointSize: 40 } GraphsTheme { id: themeQtNeonGreen theme: GraphsTheme.Theme.QtGreenNeon colorScheme: GraphsTheme.ColorScheme.Dark }
El diseño de esta aplicación va a consistir en cinco botones diferentes para activar y desactivar diferentes opciones visuales para el gráfico, y por supuesto el propio gráfico. Hay muchas formas de organizarlos, una forma es tener un GridLayout que contenga cuatro botones, el Graph, y el quinto botón, todos apareciendo en un ColumnLayout.
ColumnLayout { id: mainLayout anchors.fill: parent anchors.margins: margin spacing: spacing
El GridLayout es responsivo. Esto significa que el número de columnas utilizadas depende de la anchura de la ventana de la aplicación. Esto se hace asignando a la propiedad columns un operador ternario, que se resuelve en 1, 2 ó 4, dependiendo de la anchura de la ventana.
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)
En este GridLayout, se instancian cuatro RoundButtons. Uno para activar las sombras, otro para suavizar la malla, otro para la posición de la cámara y, por último, otro para cambiar el fondo del gráfico. Todos los botones siguen la misma estructura. En lugar de redefinir esta estructura para todos los botones, se puede hacer un componente personalizado.
component CustomButton : RoundButton { id: buttonRoot
CustomButtom extiende el tipo RoundButton, pero añade algunos complementos. Se establecen propiedades como Layout.minimumWidth, Layout.FillWidth, radius y background. Éstas definen el estilo y el diseño del botón.
property alias source: iconImage.source Layout.minimumWidth: buttonMinWidth Layout.fillWidth: true radius: mainView.radius background: Rectangle { radius: mainView.radius color: "white" border.color: "black" }
Mientras que contentItem define el contenido del botón, en este caso un tipo Row que contiene un icono y algo de texto. El icono se importa utilizando un tipo Image y estableciendo la propiedad source. El texto se crea utilizando un tipo Label y se establece utilizando su propiedad text. Se crean dos alianzas para estas dos propiedades en la parte superior del componente personalizado, lo que permitirá establecerlas cuando se cree una instancia de CustomButton.
contentItem: Row { id: content Image { id: iconImage } Label { text: buttonRoot.text horizontalAlignment: Text.AlignLeft anchors.verticalCenter: parent.verticalCenter } }
En GridLayout se crean cuatro CustomButton. Es necesario establecer tres propiedades, las dos aliadas para la imagen del icono y el texto, y la señal 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 } }
Por ejemplo, el botón de sombra establece la señal onClicked para activar y desactivar la sombra.
Configuración del gráfico
Lo siguiente en el diseño es Graph, que se define en su propio archivo QML Graph.qml, y se instanciará como sigue:
Graph { id: graph Layout.fillWidth: true Layout.fillHeight: true }
Mirando su implementación en Graph.qml, el gráfico es de tipo Scatter3D, anidado dentro de un tipo Item.
Scatter3D { id: scatterGraph
Antes de definir los conjuntos de datos, se configuran algunas de las propiedades de los ejes.
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"
Configuración de los datos
El gráfico muestra tres conjuntos de datos, que representan los datos dados en Data.qml. Los conjuntos de datos se almacenan en tipos ListModel
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 } }
y expuestos a los otros archivos usando property aliases
property alias model: dataModel property alias modelTwo: dataModelTwo property alias modelThree: dataModelThree
Antes de utilizar estos alias, cree un tipo Scatter3DSeries, que contenga un elemento ItemModelScatterDataProxy.
Scatter3DSeries { id: scatterSeries itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel" ItemModelScatterDataProxy { itemModel: seriesData.model xPosRole: "xPos" yPosRole: "yPos" zPosRole: "zPos" } }
Este proxy de datos hace referencia a los conjuntos de datos en Data.qml utilizando su propiedad itemModel. Se accede a los alias mencionados anteriormente a través de id del tipo Data instanciado en main.qml, seriesData.
itemModel: seriesData.model
Repita este procedimiento para los dos conjuntos de datos restantes.
Scatter3DSeries { id: scatterSeriesTwo ... ItemModelScatterDataProxy { itemModel: seriesData.modelTwo ... } } Scatter3DSeries { id: scatterSeriesThree ... ItemModelScatterDataProxy { itemModel: seriesData.modelThree ... } }
Genial, el gráfico de dispersión apunta ahora a los tres conjuntos de datos.
Lo único que queda por hacer es añadir el botón restante, el theme button, a nuestro ColumnLayout. La única diferencia con este botón es que está situado en el lado izquierdo del diseño. Esto se consigue definiendo la propiedad Layout.alignment como Qt.AlignLeft y Layout.fillWidth como false.
CustomButton { id: themeButton Layout.alignment: Qt.AlignLeft Layout.fillWidth: false
Contenidos de ejemplo
© 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.