饼状图饼状图核心组件在 Qt Charts 中绘制饼状图主要涉及以下核心组件●QPieSeries用于存储饼状图的数据每个扇区Slice代表一个数据项。●QChart图表的核心对象管理所有的系列、图例和标题。●QChartView用于在界面上显示 QChart 的视图组件类似于 QGraphicsView。●QPieSlice表示饼状图中的单个扇区包含数据值和标签等信息。废话不多说直接实战实现案例实现案例如下图实现思路新建项目Pieseries并且添加必要的成员, 注意包含QtCharts以及在pro中添加charts库class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent nullptr); ~MainWindow(); private: Ui::MainWindow *ui; // Qt Charts 成员 QChartView *chartView; QChart *chart; QPieSeries *series; };构造函数里实现饼状图MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), chartView(new QChartView(this)) , chart(new QChart()) , series(new QPieSeries()) { ui-setupUi(this); // 初始化饼状图数据 series-append(苹果, 30); series-append(香蕉, 20); series-append(梨子, 25); series-append(橘子, 15); series-append(葡萄, 10); // 可选择突出某个扇区 QPieSlice *slice series-slices().at(0); // 突出显示 slice-setExploded(true); // label可见 slice-setLabelVisible(true); slice-setBrush(Qt::red); // 设置扇区颜色 // 添加系列到图表 chart-addSeries(series); chart-setTitle(水果销售比例); // 图例可见 chart-legend()-setVisible(true); // 右侧对齐 chart-legend()-setAlignment(Qt::AlignRight); // 设置饼状图为圆形 chart-setAnimationOptions(QChart::AllAnimations); // 设置图表到视图 chartView-setChart(chart); // 抗锯齿 chartView-setRenderHint(QPainter::Antialiasing); // 设置布局 QVBoxLayout *layout new QVBoxLayout(); layout-addWidget(chartView); QWidget *widget new QWidget(); widget-setLayout(layout); setCentralWidget(widget); this-resize(800,600); }饼状图的定制与美化(拓展)为了使饼状图更具美观性和可读性可以进行多种定制和美化操作包括设置扇区颜色和突出显示添加标签和百分比设定图表主题设置动画效果修改图例位置和样式设置扇区颜色可以为不同的扇区设置不同的颜色以增强视觉效果。QPieSlice *slice1 series-slices().at(0); slice1-setBrush(Qt::red); QPieSlice *slice2 series-slices().at(1); slice2-setBrush(Qt::green); QPieSlice *slice3 series-slices().at(2); slice3-setBrush(Qt::blue); QPieSlice *slice4 series-slices().at(3); slice4-setBrush(Qt::yellow); QPieSlice *slice5 series-slices().at(4); slice5-setBrush(Qt::cyan);添加标签和百分比可以为扇区添加标签并显示百分比信息。foreach (QPieSlice *slice, series-slices()) { slice-setLabelVisible(true); // 显示标签和百分比 slice-setLabel(QString(%1: %2%).arg(slice-label()).arg(slice-percentage() * 100, 0, f, 1)); }上述代码为各个扇区设置标签%2%表示%2第二个参数后面再跟一个%表示第二个参数的格式是小数点保留一位小数位为0且为浮点数设定图表主题Qt Charts 提供了多种内置主题可以快速改变图表的整体风格。chart-setTheme(QChart::ChartThemeBlueCerulean); // 可选主题列表 // ChartThemeLight, ChartThemeBlueCerulean, ChartThemeDark, ChartThemeBrownSand, // ChartThemeBlueNcs, ChartThemeHighContrast, ChartThemeBlueIcy设置动画效果通过设置动画选项使图表在数据变化时具有过渡效果。chart-setAnimationOptions(QChart::SeriesAnimations);修改图例位置和样式可以调整图例的位置和样式使其更符合界面设计需求。chart-legend()-setVisible(true); chart-legend()-setAlignment(Qt::AlignRight); chart-legend()-setFont(QFont(Arial, 10));动态更新饼状图数据在实际应用中饼状图的数据可能会随着时间或事件发生变化。以下介绍如何通过定时器动态更新饼状图的数据。演示示例定时模拟随机品类的水果数量增加并作动态显示实现细节类的声明中添加定时器以及map管理数据// 定时器用于动态更新 QTimer *timer; // 模拟数据 QMapQString, QPieSlice* _name_map;构造函数中修改数据初始化先加入map再初始化扇区// 初始化饼状图数据 series-append(苹果, 30); series-append(香蕉, 20); series-append(梨子, 25); series-append(橘子, 15); series-append(葡萄, 10); //设置标签 auto index 0; foreach (QPieSlice *slice, series-slices()) { //将索引和数据关联起来 _name_map.insert(slice-label(),slice); slice-setLabelVisible(true); // 显示标签和百分比 slice-setLabel(QString(%1: %2%).arg(slice-label()) .arg(slice-percentage() * 100, 0, f, 1)); index; }构造函数添加定时器初始化并且链接信号和槽然后启动定时器每隔两秒回调一次//创建定时器 timer new QTimer(this); // 连接定时器信号 connect(timer, QTimer::timeout, this, MainWindow::updateChart); // 每2秒更新一次 timer-start(2000);槽函数的实现void MainWindow::updateChart() { // 模拟数据变化随机增加或减少某个水果的销量 QStringList keys _name_map.keys(); //随机选择一个key QString key keys.at(QRandomGenerator::global()-bounded(keys.size())); //随机设置一个增长量-5到5 int change QRandomGenerator::global()-bounded(-5, 6); //获取slice auto *slice _name_map[key]; //增加后的值 int add_val slice-value() change ; if(add_val 0){ add_val 0; } //将数据设置进去 _name_map[key]-setValue(add_val); //并且更新label _name_map[key]-setLabel(QString(%1: %2%).arg(key) .arg(slice-percentage()*100,0,f,1)); // 可选动态调整某些扇区的突出显示 // 例如突出销量最高的水果 qreal maxValue -1; QString maxKey ; //遍历水果map for(auto iter _name_map.begin(); iter ! _name_map.end(); iter){ if(iter.value()-value() maxValue){ //更新key maxKey iter.key(); //更新最大值 maxValue iter.value()-value(); continue; } } //遍历map for(auto iter _name_map.begin(); iter ! _name_map.end(); iter){ //如果key最大则展开显示 if(iter.key() maxKey){ iter.value()-setExploded(true); iter.value()-setPen(QPen(Qt::black, 2)); }else{ iter.value()-setExploded(false); iter.value()-setPen(QPen(Qt::black, 1)); } } }优化两次循环为一次循环void MainWindow::updateChart2() { // 模拟数据变化随机增加或减少某个水果的销量 QStringList keys _name_map.keys(); //随机选择一个key QString key keys.at(QRandomGenerator::global()-bounded(keys.size())); //随机设置一个增长量-5到5 int change QRandomGenerator::global()-bounded(-5, 6); //获取slice auto *slice _name_map[key]; //增加后的值 qreal add_val slice-value() change ; if(add_val 0){ add_val 0; } //将数据设置进去 _name_map[key]-setValue(add_val); //并且更新label _name_map[key]-setLabel(QString(%1: %2%).arg(key) .arg(slice-percentage()*100,0,f,1)); // 可选动态调整某些扇区的突出显示 // 例如突出销量最高的水果 qreal maxValue -1; QPieSlice* last_slice_max nullptr; //遍历水果map for(auto iter _name_map.begin(); iter ! _name_map.end(); iter){ //当前值比最大值大就暂时更新展开 if(iter.value()-value() maxValue){ //将上一次最大的扇区设置为不可展开 if(last_slice_max){ last_slice_max-setExploded(false); last_slice_max-setPen(QPen(Qt::black, 1)); } //将本扇区设置为最大 iter.value()-setExploded(true); iter.value()-setPen(QPen(Qt::black,2)); //更新最大扇区 last_slice_max iter.value(); //更新最大值 maxValue iter.value()-value(); continue; } //当前值比最大值小设置为不展开即可 iter.value()-setExploded(false); iter.value()-setPen(QPen(Qt::black,1)); } }捕获事件信号饼状图也可以捕获点击事件和悬浮事件信号被点击时饼状图会发出信号[signal] void QPieSlice::clicked()鼠标悬浮会发出下面这个信号[signal] void QPieSlice::hovered(bool state)所以我们在构造函数里连接这两个信号并且实现对应的槽函数大家好久没用lambda表达式了这里带着大家用lambda表达式写槽函数//连接点击信号 for(auto slice : _name_map){ connect(slice,QPieSlice::clicked,[](){ // 弹出提示 QMessageBox::information(this, 扇区点击, QString(您点击了 %1销量为 %2) .arg(slice-label()).arg(slice-value())); }); } //连接悬浮信号 for(auto slice : _name_map){ connect(slice,QPieSlice::hovered, [](bool state){ if (slice state) { QString tooltipText QString(%1: 销量为 %2) .arg(slice-label()) .arg(slice-value()); QToolTip::showText(QCursor::pos(), tooltipText, chartView); } else { QToolTip::hideText(); } }); }