중첩 도넛 차트 만들기
참고: 이 예제는 '위젯을 사용한 차트 갤러리' 예제의 일부입니다.

먼저 QChartView 인스턴스를 생성하고, 이에 대해 앤티앨리어싱을 활성화해 봅시다. 그런 다음 QChartView 인스턴스에서 QChart 객체를 가져옵니다. 범례는 비활성화하고 차트의 제목을 설정합니다. 마지막 줄에서는 차트의 애니메이션을 활성화합니다.
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);도넛 차트를 정의하는 데 사용될 세 개의 변수가 정의됩니다. minSize와 maxSize는 전체 도넛의 상대적 크기를 정의합니다. minSize는 가장 작은 도넛의 상대적 내부 크기이며, maxSize는 가장 큰 도넛의 상대적 외부 크기입니다.
다음 코드 블록은 개별 도넛 차트와 그 슬라이스를 정의합니다. 먼저 새로운 QPieSeries 객체를 생성합니다. 각 도넛 차트의 슬라이스 수는 무작위로 결정됩니다. 내부 for 루프는 무작위 값을 가진 슬라이스를 생성하고, 해당 값과 동일한 레이블을 부여합니다. 다음으로 슬라이스의 레이블을 표시하도록 설정하고 색상을 흰색으로 지정합니다. 예제를 더 흥미롭게 만들기 위해 슬라이스의 hovered 신호를 위젯의 슬롯에 연결하며, 이에 대한 내부 작동 원리는 나중에 설명합니다. 마지막으로 슬라이스를 도넛에 추가합니다. 도넛의 크기는 도넛들이 서로 중첩되도록 조정됩니다. 그런 다음 도넛을 위젯의 도넛 목록과 차트에 추가합니다.
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);
}마지막으로 위젯을 애플리케이션에서 사용하는 레이아웃에 배치합니다.
auto mainLayout = new QGridLayout;
mainLayout->addWidget(chartView, 1, 1);
setLayout(mainLayout);예제를 더 흥미롭게 만들기 위해 도넛은 1.25초마다 무작위로 회전합니다.
m_updateTimer = new QTimer(this);
connect(m_updateTimer, &QTimer::timeout, this, &NestedDonutsWidget::updateRotation);
m_updateTimer->start(1250);위젯의 updatedRotation 슬롯은 아래에 정의되어 있습니다. 이 슬롯은 모든 도넛을 순회하며 각 도넛의 현재 회전 각도를 무작위 값만큼 수정합니다.
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);
}
}앞서 언급한 explodeSlice 슬롯 코드는 아래와 같습니다. 슬라이스가 ‘exploded’로 설정되면 도넛의 회전을 제어하는 타이머를 중지합니다. 그런 다음 슬라이스에서 시작 각도와 종료 각도를 가져옵니다. 선택된 슬라이스를 강조 표시하기 위해, 선택된 슬라이스가 포함된 도넛보다 바깥쪽에 위치한 다른 모든 도넛의 시작 각도와 끝 각도를 수정하여 강조 표시된 슬라이스의 경로를 ‘가리지’ 않도록 합니다. 슬라이스가 더 이상 선택되지 않으면 원래 상태로 돌아갑니다.
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.