入れ子ドーナツ・チャートの作成

注: これは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は最大のドーナツの外側の相対サイズです。

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

次のコードのブロックは、個々のドーナツとそのスライスを定義します。まず、新しいQPieSeries オブジェクトが作成されます。各ドーナツのスライス数はランダムである。内部のforループがランダムな値と同じラベルでスライスを作成する。次に、スライスのラベルが見えるように設定され、色が白に設定されます。この例をより面白くするために、スライスのホバー信号がウィジェットのスロットに接続されます。最後に、スライスがドーナツに追加されます。ドーナツのサイズは、ドーナツの入れ子になるように調整される。それから、ドーナツがウィジェットのドーナツ・リストとチャートに追加されます。

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スロットのコードを以下に示します。スライスがexplodeに設定されたら、ドーナツの回転を制御するタイマーを止める。その後、スライスの開始角度と終了角度をスライスから取得します。選択されたスライスを強調するために、選択されたスライスを含むドーナツから外側にある他のドーナツの開始角度と終了角度をすべて変更し、強調されたスライスの道を「ふさがない」ようにします。スライスが選択されなくなったら、元の状態に戻ります。

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);
}

©2024 The Qt Company Ltd. 本文書に含まれる文書の著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。