Creación de gráficos Donut anidados
Nota: Esto es parte del ejemplo de la Galería de Gráficos con Widgets.

Empecemos creando una instancia QChartView y activando el Antialiasing en ella. A continuación se obtiene un objeto QChart a partir de la instancia QChartView. Se desactiva la leyenda y se establece el título del gráfico. La última línea habilita las animaciones del gráfico.
auto chartView = new QChartView(this); chartView->setRenderHint(QPainter::Antialiasing); QChart *chart = chartView->chart(); chart->legend()->setVisible(false); chart->setTitle("Nested Donuts (Hover over segments to explode them)"); chart->setAnimationOptions(QChart::AllAnimations); chart->layout()->setContentsMargins(0, 0, 0, 0);
Se definen tres variables que se utilizarán para definir el gráfico de donuts. MinSize es el tamaño interior relativo del donut más pequeño. maxSize es el tamaño exterior relativo del donut más grande.
El siguiente bloque de código define los donuts individuales y sus porciones. Primero se crea un nuevo objeto QPieSeries. El número de rebanadas de cada donut es aleatorio. El bucle for interno crea las rebanadas con un valor aleatorio y una etiqueta igual al valor. A continuación, la etiqueta de la rebanada se establece para ser visible y su color se establece en blanco. Para que el ejemplo resulte más interesante, la señal de "hover" de la rodaja se conecta a la ranura del widget, cuyo funcionamiento interno se explica más adelante. Por último, la rodaja se añade al donut. El tamaño del donut se ajusta para conseguir el anidamiento de los donuts. A continuación, el donut se añade a la lista de donuts del widget y al gráfico.
for (int i = 0; i < donutCount; i++) { auto donut = new QPieSeries; int sliceCount = 3 + QRandomGenerator::global()->bounded(3); for (int j = 0; j < sliceCount; j++) { qreal value = 100 + QRandomGenerator::global()->bounded(100); auto slice = new QPieSlice(QString("%1").arg(value), value); slice->setLabelVisible(true); slice->setLabelColor(Qt::white); slice->setLabelPosition(QPieSlice::LabelInsideTangential); connect(slice, &QPieSlice::hovered, this, &NestedDonutsWidget::explodeSlice); donut->append(slice); donut->setHoleSize(minSize + i * (maxSize - minSize) / donutCount); donut->setPieSize(minSize + (i + 1) * (maxSize - minSize) / donutCount); } m_donuts.append(donut); chartView->chart()->addSeries(donut); }
Por último, el widget se coloca en un diseño utilizado por la aplicación.
auto mainLayout = new QGridLayout; mainLayout->addWidget(chartView, 1, 1); setLayout(mainLayout);
Para hacer el ejemplo más interesante, los donuts se rotan aleatoriamente cada 1,25 segundos.
m_updateTimer = new QTimer(this); connect(m_updateTimer, &QTimer::timeout, this, &NestedDonutsWidget::updateRotation); m_updateTimer->start(1250);
La ranura updatedRotation del widget se define a continuación. Recorre todos los donuts y modifica su rotación actual por un valor aleatorio.
void NestedDonutsWidget::updateRotation() { for (int i = 0; i < m_donuts.count(); i++) { QPieSeries *donut = m_donuts.at(i); qreal phaseShift = -50 + QRandomGenerator::global()->bounded(100); donut->setPieStartAngle(donut->pieStartAngle() + phaseShift); donut->setPieEndAngle(donut->pieEndAngle() + phaseShift); } }
El código de la ranura explodeSlice mencionado anteriormente se proporciona a continuación. Si la rebanada se establece en explotado, a continuación, detener el temporizador que controla la rotación de los donuts. Entonces se obtienen los ángulos inicial y final de la rebanada. Para resaltar la rebanada seleccionada, se modifican los ángulos inicial y final de todas las demás rosquillas que se encuentran fuera de la que contiene la rebanada seleccionada, para que no "bloqueen" el paso de la rebanada resaltada. Si la rebanada deja de estar seleccionada, vuelve al estado original.
void NestedDonutsWidget::explodeSlice(bool exploded) { auto slice = qobject_cast<QPieSlice *>(sender()); if (exploded) { m_updateTimer->stop(); qreal sliceStartAngle = slice->startAngle(); qreal sliceEndAngle = slice->startAngle() + slice->angleSpan(); QPieSeries *donut = slice->series(); qreal seriesIndex = m_donuts.indexOf(donut); for (int i = seriesIndex + 1; i < m_donuts.count(); i++) { m_donuts.at(i)->setPieStartAngle(sliceEndAngle); m_donuts.at(i)->setPieEndAngle(360 + sliceStartAngle); } } else { for (int i = 0; i < m_donuts.count(); i++) { m_donuts.at(i)->setPieStartAngle(0); m_donuts.at(i)->setPieEndAngle(360); } m_updateTimer->start(); } slice->setExploded(exploded); }
© 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.