绘制饼图详细过程

QtCharts绘制饼图

说明:qcustomplot模块没有绘制饼图的接口和模块,所以用Qt官方自带的QtCharts进行绘制。绘制出来还挺美观。

1 模块导入

c++ 复制代码
QT       += charts
c++ 复制代码
QT_BEGIN_NAMESPACE

以上这两行代码必须得加

2 总体代码

  • widget.h
c++ 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtCharts>
#include <QChartView>
#include "qcustomplot.h"
#include <QTimer>
#include <QRandomGenerator>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public:
    void paintPie(QChartView *chartView);

private:
    Ui::Widget *ui;
    QTimer *timer;
};
#endif // WIDGET_H
  • widget.cpp
c++ 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    paintPie(ui->graphicsView);
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this,[this]()
    {
        // 预定义的类别名称数组
        static const QStringList categoryNames = {
               "Search Engine",
               "Direct",
               "Email",
               "Union Ads",
               "Video Ads"
           };
        QPieSeries *series = static_cast<QPieSeries *>(ui->graphicsView->chart()->series().at(0));
        QList<QPieSlice*> slices = series->slices();
        if (slices.size() >= 5)
        {
            slices[0]->setValue(QRandomGenerator::global()->bounded(10, 100));
            slices[1]->setValue(QRandomGenerator::global()->bounded(10, 100));
            slices[2]->setValue(QRandomGenerator::global()->bounded(10, 100));
            slices[3]->setValue(QRandomGenerator::global()->bounded(10, 100));
            slices[4]->setValue(QRandomGenerator::global()->bounded(10, 100));
        }
        for (int i = 0; i < slices.size(); i++)
        {
            qreal percent = (slices[i]->value() / series->sum()) * 100.0;
//            修改了这句代码,slice->label()会获取标签值,然后在标签值后不断追加数据
//            label = QString("%1\n%2%").arg(slice->label()).arg(percent, 0, 'f', 1);
            QString label = QString("%1\n%2%").arg(categoryNames[i]).arg(percent, 0, 'f', 1);
            slices[i]->setLabel(label);
            slices[i]->setLabelVisible(true);
            slices[i]->setLabelArmLengthFactor(0.05);
            slices[i]->setLabelPosition(QPieSlice::LabelOutside);
        }

    });
    timer->start(1000);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintPie(QChartView *chartView)
{
    // 创建饼图对象
    QPieSeries *series = new QPieSeries();
    series->setHoleSize(0.35);  // 空心圆大小(0-1)
    series->setPieSize(0.7);     // 饼图相对视图的大小

    // 创建Chart画布
    QChart *chart = new QChart();
    chartView->setBackgroundBrush(QBrush(QColor(Qt::black)));
    chart->setBackgroundBrush(QBrush(QColor(Qt::black)));
    chart->addSeries(series);
    chart->setAnimationOptions(QChart::AllAnimations); // 设置显示时的动画效果
    chart->setTitle("系统CPU利用率");
    chart->setTitleFont(QFont("Arial", 14, QFont::Bold));
    // 将参数设置到画布
    chartView->setChart(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
    chartView->chart()->setTheme(QChart::ChartTheme(0));
    chartView->setRubberBand(QChartView::RectangleRubberBand);  // 矩形缩放
    // 添加数据切片
    QPieSlice *slice1 = series->append("Search Engine", 1048);
    QPieSlice *slice2 = series->append("Direct", 735);
    QPieSlice *slice3 = series->append("Email", 580);
    QPieSlice *slice4 = series->append("Union Ads", 484);
    QPieSlice *slice5 = series->append("Video Ads", 300);

    // 配置每个切片的样式
    slice1->setColor(QColor(92, 123, 217));
    slice2->setColor(QColor(159, 224, 128));
    slice3->setColor(QColor(255, 220, 96));
    slice4->setColor(QColor(255, 112, 112));
    slice5->setColor(QColor(126, 211, 244));

    // 设置标签格式:显示百分比和名称
    for (auto slice : series->slices()) {
       qreal percent = (slice->value() / series->sum()) * 100.0;
       QString label = QString("%1\n%2%").arg(slice->label()).arg(percent, 0, 'f', 1);
       slice->setLabel(label);
       slice->setLabelVisible(true);
       slice->setLabelArmLengthFactor(0.05);  // 标签连接线长度
       slice->setLabelPosition(QPieSlice::LabelOutside);  // 标签在外部
//       slice->setBorderWidth(2);  // 切片边框宽度
    }

    // 配置图例
    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignTrailing);
    chart->legend()->setFont(QFont("Arial", 9));


    // 连接悬停信号(突出显示效果)
    connect(series, &QPieSeries::hovered, [](QPieSlice *slice, bool state)
    {
       if (state)
       {
           slice->setExploded(true);      // 突出显示
           slice->setLabelVisible(true);  // 确保标签可见
       }
       else
       {
           slice->setExploded(false);
           slice->setPen(QPen(Qt::NoPen));
       }
    });


}

3 逐段代码看效果

c++ 复制代码
// 创建饼图对象
QPieSeries *series = new QPieSeries();
series->setHoleSize(0.35);  // 空心圆大小(0-1)
series->setPieSize(0.7);     // 饼图相对视图的大小

// 创建Chart画布
QChart *chart = new QChart();
// 将饼图对象加入画布中
chart->addSeries(series);

// 设置界面打开时有动画显示
chart->setAnimationOptions(QChart::AllAnimations); // 设置显示时的动画效果
chart->setTitle("饼图示例");
chart->setTitleFont(QFont("Arial", 14, QFont::Bold));
// 将画布设置到视图
chartView->setChart(chart);
chartView->setRenderHint(QPainter::Antialiasing);
chartView->chart()->setTheme(QChart::ChartTheme(0));
chartView->setRubberBand(QChartView::RectangleRubberBand);  // 矩形缩放

上述代码是标准操作流程

接下来才是操作饼图

c++ 复制代码
// 添加数据切片
QPieSlice *slice1 = series->append("Search Engine", 1048);
QPieSlice *slice2 = series->append("Direct", 735);
QPieSlice *slice3 = series->append("Email", 580);
QPieSlice *slice4 = series->append("Union Ads", 484);
QPieSlice *slice5 = series->append("Video Ads", 300);
// 配置每个切片的样式
slice1->setColor(QColor(92, 123, 217));
slice2->setColor(QColor(159, 224, 128));
slice3->setColor(QColor(255, 220, 96));
slice4->setColor(QColor(255, 112, 112));
slice5->setColor(QColor(126, 211, 244));
c++ 复制代码
series->setHoleSize(0);  // 空心圆大小(0-1)
series->setPieSize(0.7);     // 饼图相对视图的大小
c++ 复制代码
series->setHoleSize(1);  // 空心圆大小(0-1)
series->setPieSize(0.7);     // 饼图相对视图的大小

这样,基础的饼图就绘制出来了,接下来是配置

c++ 复制代码
// 设置标签格式:显示百分比和名称
for (auto slice : series->slices())
{
	qreal percent = (slice->value() / series->sum()) * 100.0;
    QString label = QString("%1\n%2%").arg(slice->label()).arg(percent, 0, 'f', 1);
    slice->setLabel(label);
    slice->setLabelVisible(true);
    slice->setLabelArmLengthFactor(0.05);  // 标签连接线长度
    slice->setLabelPosition(QPieSlice::LabelOutside);  // 标签在外部
   // slice->setBorderWidth(2);  // 切片边框宽度
}
c++ 复制代码
slice->setLabelPosition(QPieSlice::LabelInsideNormal);
c++ 复制代码
// 配置图例
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignTrailing);
chart->legend()->setFont(QFont("Arial", 9));
c++ 复制代码
// 连接悬停信号(突出显示效果)
connect(series, &QPieSeries::hovered, [](QPieSlice *slice, bool state)
{
   if (state)
   {
       slice->setExploded(true);      // 突出显示
       slice->setLabelVisible(true);  // 确保标签可见
   }
   else
   {
       slice->setExploded(false);
       slice->setPen(QPen(Qt::NoPen));
   }
});

4 让饼图动态显示

c++ 复制代码
// 首先,肯定要有一个定时器吧
timer = new QTimer(this);

connect(timer, &QTimer::timeout, this,[this]()
{
    // 预定义的类别名称数组
    static const QStringList categoryNames = {
               "Search Engine",
               "Direct",
               "Email",
               "Union Ads",
               "Video Ads"
     };
     // 获取饼图的切片
     QPieSeries *series = static_cast<QPieSeries *>(ui->graphicsView->chart()->series().at(0));
     QList<QPieSlice*> slices = series->slices();
     if (slices.size() >= 5)
     {
     	// 这里直接用索引,没有用series->append
     	slices[0]->setValue(QRandomGenerator::global()->bounded(10, 100));
        slices[1]->setValue(QRandomGenerator::global()->bounded(10, 100));
        slices[2]->setValue(QRandomGenerator::global()->bounded(10, 100));
        slices[3]->setValue(QRandomGenerator::global()->bounded(10, 100));
        slices[4]->setValue(QRandomGenerator::global()->bounded(10, 100));
     }
     for (int i = 0; i < slices.size(); i++)
     {
     	qreal percent = (slices[i]->value() / series->sum()) * 100.0;
//            修改了这句代码,slice->label()会获取标签值,然后在标签值后不断追加数据
//            label = QString("%1\n%2%").arg(slice->label()).arg(percent, 0, 'f', 1);
        QString label = QString("%1\n%2%").arg(categoryNames[i]).arg(percent, 0, 'f', 1);
        slices[i]->setLabel(label);
        slices[i]->setLabelVisible(true);
        slices[i]->setLabelArmLengthFactor(0.05);
        slices[i]->setLabelPosition(QPieSlice::LabelOutside);
    }

});
timer->start(1000);
相关推荐
EasyGBS7 分钟前
从接入到稳定播放:无插件直播H5视频流媒体播放器EasyPlayer.js如何撑起Web端流媒体
开发语言·前端·javascript
FfHUCisI9 分钟前
GMP 调度器:Go 并发的心脏是如何跳动的
开发语言·golang·php
Java小白笔记16 分钟前
Java 实现阿里云 OSS 文件上传链路:普通上传、秒传、分片与断点续传
java·开发语言·数据库·spring·阿里云
传奇开心果编程18 分钟前
【Rust入门知识点学与练】第9课:Vec 动态数组
开发语言·学习·rust
卢锡荣21 分钟前
单芯掌控多口互联|乐得瑞 LDR6020 PD3.1 多通道 Type‑C 控制 SOC 芯片
c语言·开发语言
2333!!!!!21 分钟前
rocket新手一些常见问题
java·开发语言
yume_sibai23 分钟前
02-Rust 所有权与借用深入解析(底层原理 + 借用检查器 + 生命周期 + 内部可变性)
开发语言·后端·rust
xxwxx__25 分钟前
深入理解 C++ STL:stack、queue 与 deque 从使用到底层实现全解析
开发语言·c++·算法
Highcharts.js26 分钟前
甘特图纵向任务、横向时间显示图表可视化开发|Highcharts甘特图示例
开发语言·前端·javascript·可视化·甘特图·数据可视化·highcharts
wuminyu31 分钟前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++