Erstellen von verschachtelten Ringdiagrammen
Hinweis: Dies ist Teil des Beispiels „Diagramme mit Widgets-Galerie “.

Zunächst erstellen wir eine QChartView-Instanz und aktivieren dort die Kantenglättung. Anschließend wird aus der QChartView-Instanz ein QChart-Objekt abgerufen. Die Legende wird deaktiviert und der Titel des Diagramms festgelegt. In der letzten Zeile werden die Animationen des Diagramms aktiviert.
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);Es werden drei Variablen definiert, die zur Gestaltung des Ringdiagramms verwendet werden. „min“ und „maxSize“ legen die relative Größe des gesamten Rings fest. „minSize“ ist die relative innere Größe des kleinsten Rings. „maxSize“ ist die relative äußere Größe des größten Rings.
Der folgende Codeabschnitt definiert die einzelnen Ringdiagramme und ihre Segmente. Zunächst wird ein neues QPieSeries-Objekt erstellt. Die Anzahl der Segmente in jedem Ringdiagramm wird zufällig festgelegt. Die interne for-Schleife erstellt die Segmente mit einem Zufallswert und einer Beschriftung, die dem Wert entspricht. Anschließend wird die Beschriftung des Segments als sichtbar festgelegt und seine Farbe auf Weiß gesetzt. Um das Beispiel interessanter zu gestalten, wird das „hovered“-Signal des Segments mit dem Slot des Widgets verbunden, dessen Funktionsweise später erläutert wird. Schließlich wird der Ausschnitt dem Donut hinzugefügt. Die Größe des Donuts wird angepasst, um die Verschachtelung der Donuts zu erreichen. Dann wird der Donut zur Donut-Liste des Widgets und zum Diagramm hinzugefügt.
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);
}Schließlich wird das Widget in ein von der Anwendung verwendetes Layout eingefügt.
auto mainLayout = new QGridLayout;
mainLayout->addWidget(chartView, 1, 1);
setLayout(mainLayout);Um das Beispiel interessanter zu gestalten, werden die Donuts alle 1,25 Sekunden zufällig gedreht.
m_updateTimer = new QTimer(this);
connect(m_updateTimer, &QTimer::timeout, this, &NestedDonutsWidget::updateRotation);
m_updateTimer->start(1250);Der Slot „updatedRotation“ des Widgets ist unten definiert. Er durchläuft alle Donuts und ändert deren aktuelle Drehung um einen Zufallswert.
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);
}
}Der zuvor erwähnte Code für den „explodeSlice“-Slot ist unten aufgeführt. Wenn der Slice auf „exploded“ gesetzt ist, wird der Timer gestoppt, der die Drehung der Donuts steuert. Anschließend werden der Start- und Endwinkel des Slices aus dem Slice selbst ermittelt. Um den ausgewählten Ausschnitt hervorzuheben, werden die Start- und Endwinkel aller anderen Donuts, die außerhalb des Donuts liegen, der den ausgewählten Ausschnitt enthält, so angepasst, dass sie den Weg für den hervorgehobenen Ausschnitt nicht „versperren“. Ist der Ausschnitt nicht mehr ausgewählt, wird der ursprüngliche Zustand wiederhergestellt.
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.