Gráfico de barras simple
Usando Bars3D en una aplicación QML.
Simple Bar Graph muestra cómo hacer un simple gráfico de barras en 3D utilizando Bars3D y QML.

Las siguientes secciones describen cómo cambiar de serie y mostrar más de una serie a la vez. Para obtener más información sobre la funcionalidad básica de la aplicación QML, consulte Simple Scatter Graph.
Ejecución del ejemplo
Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para obtener más información, consulte Qt Creator: Tutorial: Construir y ejecutar.
Datos
El conjunto de datos del ejemplo son los ingresos y gastos mensuales de una empresa ficticia a lo largo de varios años. Los datos se definen en un modelo de lista en Data.qml de la siguiente manera:
ListModel { id: dataModel ListElement{ timestamp: "2016-01"; expenses: "-4"; income: "5" } ListElement{ timestamp: "2016-02"; expenses: "-5"; income: "6" } ListElement{ timestamp: "2016-03"; expenses: "-7"; income: "4" } ...
Cada dato tiene tres funciones: marca de tiempo, ingresos y gastos. El valor de la marca de tiempo tiene el formato: <four digit year>-<two digit month>. Normalmente, se asignarían los años y los meses a las filas y columnas de un gráfico de barras, pero sólo se pueden mostrar los ingresos o los gastos como valor.
Ahora, añade los datos al gráfico Bars3D. Crea dos Bar3DSeries dentro de él, empezando con una serie para los ingresos:
Bar3DSeries { id: barSeries itemLabelFormat: "Income, @colLabel, @rowLabel: @valueLabel" baseGradient: barGradient ItemModelBarDataProxy { id: modelProxy itemModel: graphData.model rowRole: "timestamp" columnRole: "timestamp" valueRole: "income" rowRolePattern: /^(\d\d\d\d).*$/ columnRolePattern: /^.*-(\d\d)$/ rowRoleReplace: "\\1" columnRoleReplace: "\\1" multiMatchBehavior: ItemModelBarDataProxy.MultiMatchBehavior.Cumulative } ...
Los datos se adjuntan a la propiedad itemModel del ItemModelBarDataProxy dentro de la serie. Para el valueRole, especifique el campo income ya que contiene el valor deseado. Obtener los años y los meses es un poco más complicado ya que ambos se encuentran en el mismo campo. Para extraer estos valores, especifique el campo timestamp tanto para rowRole como para columnRole. Además, especifique un patrón de búsqueda y una regla de sustitución para esas funciones con el fin de extraer la parte correcta del contenido del campo para cada función. El patrón de búsqueda es una expresión regular normal de JavaScript, y la regla de sustitución especifica con qué se sustituye el contenido del campo que coincide con la expresión regular. En este caso, sustituye todo el contenido del campo por sólo el año o el mes, que es la primera subcadena capturada tanto para las filas como para las columnas. Para obtener más información sobre la función de sustitución con expresiones regulares, consulte la documentación de la función QString::replace(const QRegExp &rx, const QString &after).
La propiedad multiMatchBehavior especifica qué hacer en caso de que varios elementos del modelo de elementos coincidan con la misma combinación de fila/columna. En este caso, suma sus valores. Esta propiedad no tiene efecto cuando se muestran valores para cada mes, ya que no hay meses duplicados en nuestro modelo de ítems. Sin embargo, será relevante más adelante cuando quiera mostrar los totales anuales.
A continuación, añada otra serie para los gastos:
Bar3DSeries { id: secondarySeries visible: false itemLabelFormat: "Expenses, @colLabel, @rowLabel: -@valueLabel" baseGradient: secondaryGradient ItemModelBarDataProxy { id: secondaryProxy itemModel: graphData.model rowRole: "timestamp" columnRole: "timestamp" valueRole: "expenses" rowRolePattern: /^(\d\d\d\d).*$/ columnRolePattern: /^.*-(\d\d)$/ valueRolePattern: /-/ rowRoleReplace: "\\1" columnRoleReplace: "\\1" multiMatchBehavior: ItemModelBarDataProxy.MultiMatchBehavior.Cumulative } ...
El modelo contiene los gastos como valores negativos, pero podrían mostrarse como barras positivas para facilitar la comparación con las barras de ingresos. Utilice valueRolePattern para eliminar el signo menos, y no es necesario especificar ninguna cadena de sustitución, ya que la sustitución por defecto es una cadena vacía.
Utilice la propiedad visible de la serie para ocultar la segunda serie por ahora.
Etiquetas de eje personalizadas
Axes.qml redefine las etiquetas de categoría para el eje de columnas porque los datos contienen números para los meses, lo que desordenarían las etiquetas:
Category3DAxis { id: columnAxis labels: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] labelAutoAngle: 30 }
Para que las etiquetas de los ejes sean más legibles en ángulos de cámara bajos, establezca la rotación automática de las etiquetas de los ejes.
Cambio de series
En main.qml, configure el gráfico y varios elementos de la interfaz de usuario. Hay tres bloques de código interesantes a destacar aquí. El primero muestra cómo cambiar los datos visualizados entre ingresos, gastos y ambos, simplemente cambiando la visibilidad de las dos series:
onClicked: { if (text === "Show Expenses") { barSeries.visible = false secondarySeries.visible = true barGraph.valueAxis.labelFormat = "-%.2f M\u20AC" secondarySeries.itemLabelFormat = "Expenses, @colLabel, @rowLabel: @valueLabel" text = "Show Both" } else if (text === "Show Both") { barSeries.visible = true barGraph.valueAxis.labelFormat = "%.2f M\u20AC" secondarySeries.itemLabelFormat = "Expenses, @colLabel, @rowLabel: -@valueLabel" text = "Show Income" } else { // text === "Show Income" secondarySeries.visible = false text = "Show Expenses" } }
El formato de la etiqueta del eje y los formatos de la etiqueta de selección de elementos se ajustan para que el signo negativo se muestre correctamente para los gastos, que en realidad se resolvieron como valores positivos.
El segundo bloque interesante es en el que se cambian los datos visualizados ajustando las propiedades del proxy:
onClicked: { if (text === "Show yearly totals") { modelProxy.autoRowCategories = true secondaryProxy.autoRowCategories = true modelProxy.columnRolePattern = /^.*$/ secondaryProxy.columnRolePattern = /^.*$/ graphAxes.value.autoAdjustRange = true barGraph.columnAxis = graphAxes.total text = "Show all years" } else if (text === "Show all years") { modelProxy.autoRowCategories = true secondaryProxy.autoRowCategories = true modelProxy.columnRolePattern = /^.*-(\d\d)$/ secondaryProxy.columnRolePattern = /^.*-(\d\d)$/ graphAxes.value.min = 0 graphAxes.value.max = 35 barGraph.columnAxis = graphAxes.column text = "Show 2020 - 2022" } else { // text === "Show 2020 - 2022" // Explicitly defining row categories, since we do not want to show data for // all years in the model, just for the selected ones. modelProxy.autoRowCategories = false secondaryProxy.autoRowCategories = false modelProxy.rowCategories = ["2020", "2021", "2022"] secondaryProxy.rowCategories = ["2020", "2021", "2022"] text = "Show yearly totals" } }
Para mostrar los totales anuales, se combinan los doce meses de cada año en una sola barra. Esto se consigue especificando un columnRolePattern que coincida con todos los elementos del modelo. De este modo, la serie sólo tendrá una única columna. El multiMatchBehavior acumulativo especificado anteriormente para el proxy pasa a ser relevante ahora, haciendo que los valores de los doce meses de cada año se sumen en una sola barra.
Para mostrar sólo un subconjunto de años, establezca autoRowCategories en false en el elemento ItemModelBarDataProxy y defina explícitamente las categorías de las filas. De este modo, sólo se visualizarán los elementos de las categorías de filas especificadas.
El tercer bloque interesante muestra cómo obtener el índice de fila y columna de un elemento si se conocen los valores de fila y columna mediante los métodos ItemModelBarDataProxy rowCategoryIndex() y columnCategoryIndex():
var timestamp = graphData.model.get(mainview.currentRow).timestamp var pattern = /(\d\d\d\d)-(\d\d)/ var matches = pattern.exec(timestamp) var rowIndex = modelProxy.rowCategoryIndex(matches[1]) var colIndex if (barGraph.columnAxis == graphAxes.total) colIndex = 0 // Just one column when showing yearly totals else colIndex = modelProxy.columnCategoryIndex(matches[2]) if (selectedSeries.visible) mainview.selectedSeries.selectedBar = Qt.point(rowIndex, colIndex) else if (barSeries.visible) barSeries.selectedBar = Qt.point(rowIndex, colIndex) else secondarySeries.selectedBar = Qt.point(rowIndex, colIndex)
© 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.