Création de diagrammes en beignet imbriqués
Note : Ceci fait partie de l'exemple de la galerie Charts with Widgets.

Commençons par créer une instance QChartView et par activer l'anticrénelage. Un objet QChart est ensuite obtenu à partir de l'instance QChartView. La légende est désactivée et le titre du graphique est défini. La dernière ligne active les animations du graphique.
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);
Trois variables sont définies, qui seront utilisées pour définir le graphique en forme de beignet. Min et max size définissent la taille relative de l'ensemble du donut. minSize est la taille intérieure relative du plus petit donut. maxSize est la taille extérieure relative du plus grand donut.
Le bloc de code suivant définit les beignets individuels et leurs tranches. Un nouvel objet QPieSeries est d'abord créé. Le nombre de tranches dans chaque donut est aléatoire. La boucle for interne crée les tranches avec une valeur aléatoire et une étiquette identique à la valeur. Ensuite, l'étiquette de la tranche est rendue visible et sa couleur est fixée au blanc. Pour rendre l'exemple plus intéressant, le signal survolé de la tranche est connecté au slot du widget, dont le fonctionnement interne est expliqué plus loin. Enfin, la tranche est ajoutée au donut. La taille du donut est ajustée pour obtenir l'imbrication des donuts. Le beignet est ensuite ajouté à la liste des beignets du widget et au graphique.
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); }
Enfin, le widget est placé dans une disposition utilisée par l'application.
auto mainLayout = new QGridLayout; mainLayout->addWidget(chartView, 1, 1); setLayout(mainLayout);
Pour rendre l'exemple plus intéressant, les donuts sont tournés aléatoirement toutes les 1,25 secondes.
m_updateTimer = new QTimer(this); connect(m_updateTimer, &QTimer::timeout, this, &NestedDonutsWidget::updateRotation); m_updateTimer->start(1250);
Le slot updatedRotation du widget est défini ci-dessous. Il passe en revue tous les donuts et modifie leur rotation actuelle par une valeur aléatoire.
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); } }
Le code du slot explodeSlice mentionné plus haut est fourni ci-dessous. Si la tranche est réglée sur exploded, le timer qui contrôle la rotation des donuts est arrêté. Ensuite, les angles de début et de fin de la tranche sont obtenus à partir de la tranche. Pour mettre en évidence la tranche sélectionnée, tous les autres donuts qui se trouvent à l'extérieur de celui qui contient la tranche sélectionnée voient leurs angles de départ et d'arrivée modifiés de manière à ne pas "bloquer" le passage à la tranche mise en évidence. Si la tranche n'est plus sélectionnée, revenez à l'état initial.
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.