创建嵌套环形图

注意: 这是 带有小部件库的图表集 示例的一部分。

首先创建一个 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 是最大环形图的外径大小。

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

以下代码块定义了单个环形图及其切片。首先创建一个新 QPieSeries 对象。每个环形图的切片数量是随机的。内部循环创建切片,带有随机的值和标签,标签与值相同。接下来设置切片的标签为可见,并将其颜色设置为白色。为了使示例更加有趣,将切片的悬停信号连接到小部件的槽。其内部工作原理将在稍后解释。最后将切片添加到环形图中。调整环形图的大小以实现环形图的嵌套。然后将环形图添加到小部件的环形图列表和图表中。

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 槽代码。如果设置切片为爆炸,则停止控制环形图旋转的计时器。然后从切片中获取切片的起始和结束角度。为了突出显示所选切片,将所有其他位于所选切片外部环形图的起始和结束角度修改,以避免阻碍突出的切片。如果切片不再被选中,则返回到原始状态。

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 Qt 公司有限公司。在此包含的文档贡献是各自所有者的版权。此处提供的文档是根据 Free Software Foundation 发布的 GNU 自由文档许可证版本 1.3 的条款发布的。Qt 及相关标志是芬兰以及/或全球其他地区的 Qt 公司有限公司的商标。所有其他商标均为其各自所有者的财产。