ネストされたドーナツグラフの作成

注:これは 「Charts with Widgets Gallery」サンプルの一部です。

複数のドーナツグラフを組み合わせた図を示したスクリーンショット

まず、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);

ドーナツチャートを定義するために、3つの変数が定義されます。minSizeとmaxSizeは、ドーナツ全体の相対的なサイズを定義します。minSizeは、最小のドーナツの相対的な内径です。maxSizeは、最大のドーナツの相対的な外径です。

qreal minSize = 0.1;
qreal maxSize = 0.9;
int donutCount = 5;

次のコードブロックでは、個々のドーナツチャートとそのスライスを定義します。まず、新しい 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.