Creación de gráficos de cajas y bigotes

Nota: Esto es parte del ejemplo de la Galería de Gráficos con Widgets.

El ejemplo también muestra cómo leer los datos no continuos de un archivo, organizarlos y encontrar las medianas necesarias para el trazado de cajas y bigotes.

Captura de pantalla de un gráfico de cajas y bigotes

Para mostrar la desviación de las acciones de dos compañías comenzamos creando dos QBoxPlotSeries para manejar los datos mensuales.

auto acmeSeries = new QBoxPlotSeries;
acmeSeries->setName("Acme Ltd");

auto boxWhiskSeries = new QBoxPlotSeries;
boxWhiskSeries->setName("BoxWhisk Inc");

QFile La clase BoxDataReader se utiliza para abrir un fichero de texto donde se guardan los datos no continuos. El BoxDataReader es una clase auxiliar para leer el fichero de texto y encontrar los valores extremos y la mediana de los datos. El BoxDataReader se explica con más detalle más adelante. El método readBox lee los valores y los establece en el elemento QBoxSet que el método devuelve a la persona que llama. El elemento QBoxSet devuelto se añade a la serie.

QFile acmeData(":boxplot_a");
const QString errorTemplate = QStringLiteral("Failed to load '%1' file.");
if (!acmeData.open(QIODevice::ReadOnly | QIODevice::Text)) {
    m_loadError = errorTemplate.arg(acmeData.fileName());
    return false;
}

BoxPlotDataReader dataReader(&acmeData);
while (!dataReader.atEnd()) {
    QBoxSet *set = dataReader.readBox();
    if (set)
        acmeSeries->append(set);
}

En esta sección se abre un segundo fichero para leer los datos de la segunda empresa.

QFile boxwhiskData(":boxplot_b");
if (!boxwhiskData.open(QIODevice::ReadOnly | QIODevice::Text)) {
    m_loadError = errorTemplate.arg(acmeData.fileName());
    return false;
}

dataReader.readFile(&boxwhiskData);
while (!dataReader.atEnd()) {
    QBoxSet *set = dataReader.readBox();
    if (set)
        boxWhiskSeries->append(set);
}

En este fragmento de código se crea una nueva instancia de QChart y se le añaden las series creadas anteriormente. También se define el título y la animación se establece como SeriesAnimation.

auto chart = new QChart;
chart->addSeries(acmeSeries);
chart->addSeries(boxWhiskSeries);
chart->setTitle("Acme Ltd. and BoxWhisk Inc. share deviation in 2012");
chart->setAnimationOptions(QChart::SeriesAnimations);

Aquí le pedimos al gráfico que cree ejes por defecto para nuestra presentación. También establecemos el rango para el eje vertical consultando el puntero para el eje desde el gráfico, y luego estableciendo el mínimo y el máximo para ese eje.

chart->createDefaultAxes();
chart->axes(Qt::Vertical).first()->setMin(15.0);
chart->axes(Qt::Horizontal).first()->setMax(34.0);

En esta sección configuramos las leyendas para que sean visibles y las colocamos en la parte inferior del gráfico.

chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);

Por último, añadimos el gráfico a una vista. También activamos el antialiasing para el chartView.

createDefaultChartView(chart);

El gráfico está listo para ser mostrado.

Aquí se explica en detalle el método readBox.

Primero se lee una línea del fichero y se rechazan las líneas que empiezan por # ya que se consideran líneas de comentario.

QString line = m_textStream.readLine();
if (line.startsWith("#"))
    return nullptr;

En este archivo los datos están ordenados como número, espacio, número o espacio. En este fragmento, la línea se divide en cadenas de números individuales que se almacenan en QStringList.

QStringList strList = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);

La sortedList contendrá los números en orden continuo y en este segmento de código mostramos cómo hacerlo. Primero se limpia la sortedList y se leen los números de la strList y se almacenan en sortedList en formato doble. El método qSort ordena la sortedList en orden continuo empezando por el más pequeño.

m_sortedList.clear();
for (int i = 1; i < strList.count(); i++)
    m_sortedList.append(strList.at(i).toDouble());

std::sort(m_sortedList.begin(), m_sortedList.end());

A continuación encontrará un ejemplo de código que muestra cómo seleccionar los extremos y las medianas de los datos continuos. En primer lugar se crea un nuevo QBoxSet. Los extremos inferior y superior son fáciles de seleccionar; son simplemente el primer y el último elemento de la lista ordenada. Para las medianas utilizamos un método de ayuda findMedian que se explica más adelante. Para la mediana de la mitad superior necesitamos ajustar el número inicial si la cantidad de números es par o impar. El número final para la mitad inferior viene naturalmente del redondeo int.

auto box = new QBoxSet(strList.first());
box->setValue(QBoxSet::LowerExtreme, m_sortedList.first());
box->setValue(QBoxSet::UpperExtreme, m_sortedList.last());
box->setValue(QBoxSet::Median, findMedian(0, count));
box->setValue(QBoxSet::LowerQuartile, findMedian(0, count / 2));
box->setValue(QBoxSet::UpperQuartile, findMedian(count / 2 + (count % 2), count));

A continuación encontrará el ejemplo de código para el método findMedian. Si la cantidad de números es desigual seleccionamos el número del medio. Para números pares tomamos dos números del medio y calculamos el valor medio.

int count = end - begin;
if (count % 2) {
    return m_sortedList.at(count / 2 + begin);
} else {
    qreal right = m_sortedList.at(count / 2 + begin);
    qreal left = m_sortedList.at(count / 2 - 1 + begin);
    return (right + left) / 2.0;
}

© 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.