Qt example of drawing custom pie chart statistics

First give the result graph. This example is to classify various events and then count the proportions, and then draw a pie chart to display it.

This is what I copied from the official example. I modified it after letting myself understand it. To generate a pie chart, I need QT charts support. If you don’t choose this when installing QT, you need to download this module and add it in the .pro file.

QT += charts

First, rewrite the pie chart block so that when the mouse is hovering over a pie chart block, the block will pop up and then display the block information. This is relatively simple, as shown below

//头文件
#include <QtCharts/QPieSlice>

QT_CHARTS_USE_NAMESPACE

class CustomSlice : public QPieSlice
{
    Q_OBJECT

public:
    CustomSlice(QString label, qreal value);

public Q_SLOTS:
    void showHighlight(bool show);

};

//cpp文件

#include "customslice.h"

QT_CHARTS_USE_NAMESPACE

CustomSlice::CustomSlice(QString label, qreal value)
    : QPieSlice(label, value)
{
    connect(this, &CustomSlice::hovered, this, &CustomSlice::showHighlight);
}

void CustomSlice::showHighlight(bool show)
{
    setLabelVisible(show);//显示标签
    setExploded(show); // 弹出
}

The main code is as follows. It mainly initializes the pie chart, creates the pie chart, randomly colors the pie chart blocks, and sorts the display of the pie chart data. You only need to call the interface function to insert the corresponding data to generate a visual pie chart.

statisticwindow.h

#ifndef STATISTICCHARTSWINDOW_H
#define STATISTICCHARTSWINDOW_H

#include <QWidget>
#include <QVBoxLayout>
#include <QtCharts/QPieSeries>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QValueAxis>
#include <QtCharts/QChartView>

class QPushButton;
class CustomSlice;
QT_CHARTS_USE_NAMESPACE

class StatisticChartsWindow : public QWidget
{
    Q_OBJECT
public:
    explicit StatisticChartsWindow(QWidget *parent = nullptr);
    ~StatisticChartsWindow();
    //创建一个饼图1
    void createPie1(QMap<QString, int> data, QString title);
    //创建一个饼图2
    void createPie2(QMap<QString, int> data, QString title);
    // 为饼图1添加块信息
    void appendSlice1(QString lable, int value);
    // 为饼图2添加块信息
    void appendSlice2(QString lable, int value);
    // 移除所有块信息
    void removeAllSlice();
    // 获取随机颜色为饼图的每个块上色
    Qt::GlobalColor getRandomColor();
    //获取排序后的数据
    QList<QMap<QString, int>> getsortListByValue(QMap<QString, int> &data);
    QVBoxLayout *VBoxLayout;

    QPieSeries *series1;
    QPieSeries *series2;
    QChart *chart1;
    QChart *chart2;
    QChartView *chartView1;
    QChartView *chartView2;
    QPushButton *closeButton;

    QList<CustomSlice*> CustomSlice1List;
    QList<CustomSlice*> CustomSlice2List;
    QList<Qt::GlobalColor> colorList;

signals:
    void closeSig();

public slots:
};

#endif // STATISTICCHARTSWINDOW_H

statisticwindow.cpp

#include "statisticwindow.h"
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLegend>
#include <QtCharts/QPieSeries>
#include <QtCharts/QBarCategoryAxis>
#include <QtCharts/QValueAxis>
#include <QtCharts/QChartView>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSpacerItem>
#include <QRandomGenerator>
#include "customslice.h"
#include <QPushButton>
#include "pushbutton.h"

StatisticChartsWindow::StatisticChartsWindow(QWidget *parent) : QWidget(parent)
{
    VBoxLayout = new QVBoxLayout(this);
    series1 = new QPieSeries(this);// 饼图一
    chart1 = new QChart();
    chart1->setAnimationOptions(QChart::AllAnimations);
    chart1->legend()->setVisible(true);
    chart1->legend()->setAlignment(Qt::AlignRight);//设置标签在右侧
    chartView1 = new QChartView(chart1);

    series2 = new QPieSeries(this);// 饼图一
    chart2 = new QChart();
    chart2->setAnimationOptions(QChart::AllAnimations);
    chart2->legend()->setVisible(true);
    chart2->legend()->setAlignment(Qt::AlignRight);//设置标签在右侧

    chartView2 = new QChartView(chart2);

    //底部添加关闭按钮
    closeButton = new QPushButton("关闭", this);
    QHBoxLayout *hlayout = new QHBoxLayout();
    hlayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
    hlayout->addWidget(closeButton);
    hlayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));

    //SC3C::Valwell::PushButton::initStyle(closeButton);
    QPalette palette = closeButton->palette();
    QColor color(19, 46, 74); // RGB红色
    palette.setColor(QPalette::Button, color);
    closeButton->setPalette(palette);
    closeButton->setStyleSheet("color: white;");

    colorList<<Qt::red<<Qt::white<<Qt::darkGray<<Qt::gray<<Qt::lightGray<<Qt::red<<Qt::green<<Qt::blue<<Qt::cyan
            <<Qt::magenta<<Qt::yellow<<Qt::darkRed<<Qt::darkGreen<<Qt::darkBlue<<Qt::darkCyan;


    chartView1->chart()->setTheme(QChart::ChartThemeBlueCerulean);
    chartView2->chart()->setTheme(QChart::ChartThemeBlueCerulean);
    VBoxLayout->addWidget(chartView1);
    VBoxLayout->addWidget(chartView2);
    VBoxLayout->addLayout(hlayout);
    VBoxLayout->layout()->setSpacing(1);//底部添加关闭

    connect(closeButton, &QPushButton::clicked, [=]() {
        this->hide();
        emit closeSig();
    });
    this->setWindowFlags(this->windowFlags() | Qt::WindowCloseButtonHint);
    this->setStyleSheet("background-color: rgb(19, 46, 74);");
}

StatisticChartsWindow::~StatisticChartsWindow()
{
    if(chart1) {
        delete  chart1;
    }
    if(chart2) {
        delete  chart2;
    }
}

void StatisticChartsWindow::createPie1(QMap<QString, int> data, QString title)
{
    // 创建一个饼图系列
    series1->clear();
    int count=0; //计算总数
    QMap<int, QList<QString>> map;

    for(auto it=data.begin(); it!=data.end(); it++) {
        count += it.value();
    }

    QList<QMap<QString, int>> sortList = getsortListByValue(data);// 根据条数比例排序,从大到小

    for(QMap<QString, int> map: sortList) {
        QString keyLable = map.firstKey();
        int num = map.value(keyLable);
        double ratio = num/1.0/count*100;

        QString ratioStr = QString::number(ratio, 'f', 1);
        QString lable = QString("%1,条数:%2,占比,%3%").arg(keyLable).arg(num).arg(ratioStr);
        appendSlice1(lable, num); // 添加到饼图中
    }
    // 创建一个新的图表并添加系列
    chart1->setTitle(title);
    //chart1->removeAllSeries();
    chart1->addSeries(series1);
}

void StatisticChartsWindow::createPie2(QMap<QString, int> data, QString title)
{
    // 创建一个饼图系列
    series2->clear();
    int count=0; //计算总数
    QMap<int, QList<QString>> map;

    for(auto it=data.begin(); it!=data.end(); it++) {
        count += it.value();
    }

    QList<QMap<QString, int>> sortList = getsortListByValue(data);

    for(QMap<QString, int> map: sortList) {
        QString keyLable = map.firstKey();
        int num = map.value(keyLable);
        double ratio = num/1.0/count*100;

        QString ratioStr = QString::number(ratio, 'f', 1);
        QString lable = QString("%1,条数:%2,占比,%3%").arg(keyLable).arg(num).arg(ratioStr);
        appendSlice2(lable, num);
    }
    // 创建一个新的图表并添加系列
    chart2->setTitle(title);
    //chart2->removeAllSeries();
    chart2->addSeries(series2);
}

void StatisticChartsWindow::appendSlice1(QString lable, int value)
{
    CustomSlice *customSlice = new  CustomSlice(lable, value);
    customSlice->setBrush(QBrush(getRandomColor())); //设置填充颜色
    //customSlice->setPen(QPen(Qt::black)); //设置线条颜色

    CustomSlice1List.append(customSlice);
    *series1 << customSlice;
}

void StatisticChartsWindow::appendSlice2(QString lable, int value)
{
    CustomSlice *customSlice = new  CustomSlice(lable, value);
    customSlice->setBrush(QBrush(getRandomColor())); //设置填充颜色
    CustomSlice2List.append(customSlice);
    *series2 << customSlice;}

void StatisticChartsWindow::removeAllSlice()
{
    for(CustomSlice* custom: CustomSlice1List) {
        series1->remove(custom);
    }
    for(CustomSlice* custom: CustomSlice2List) {
        series2->remove(custom);
    }
    qDeleteAll(CustomSlice1List);
    qDeleteAll(CustomSlice2List);
    CustomSlice1List.clear();
    CustomSlice2List.clear();
}

Qt::GlobalColor StatisticChartsWindow::getRandomColor()
{
    int randomValue = QRandomGenerator::global()->bounded(0, colorList.size()-1);
    return colorList.takeAt(randomValue);
}

QList<QMap<QString, int>> StatisticChartsWindow::getsortListByValue(QMap<QString, int> &data)
{
    QList<QMap<QString, int>> sortList;
    QList<int> valueList;
    for(auto it=data.begin(); it!=data.end(); it++) {
        if(!valueList.contains(it.value())) {
            valueList.append(it.value());
        }
    }
    //根据值逆序排序
    std::sort(valueList.begin(), valueList.end(), std::greater<int>());

    for(int value: valueList) {
        for(QString key: data.keys(value)) {
            QMap<QString, int> map;
            map.insert(key, value);
            sortList.append(map);
        }
    }
    return sortList;
}

My example is that after clicking the statistics button, the corresponding data is obtained, and then the corresponding pie chart is generated.

    QObject::connect(ui.statisticsBtn, &QPushButton::clicked, [=]() {
        g_dataCache->setSystemLog(SC3C::eSystemLogType::QUERY_SYSTEMLOG, QString("成功"),"查看日志统计");
        StatisticChartsWindow window;
        if(StatisticWindow) {
            tableView->hide();
            StatisticWindow->show();
            return;
        }
        StatisticWindow = new StatisticChartsWindow(q);
        QObject::connect(StatisticWindow, &StatisticChartsWindow::closeSig, q, [=]() {
            tableView->show();
        });
        //  标签名,  数量
        QMap<QString, int> map1 = { };
        QMap<QString, int> map2 = { };
        int logType = ui.logType->currentData().toInt();
        int eventType = ui.eventType->currentData().toInt();
        QString Name = ui.operatorName->currentText();
        tableModel.second->setFilterOperator("所有");
        // 获取数据,map1表示饼图一需要的数据
        getEventTypeStatisticHash(map1, map2);
        //恢复之前显示的
        tableModel.second->setFilterType(logType, eventType);
        tableModel.second->setFilterOperator(Name);
        //SC3C::Valwell::Widget::setBackgroundCommon2WithMargins(window);
        StatisticWindow->setFixedSize(q->size());
        //StatisticWindow->setStyleSheet("background-color: transparent;");
        StatisticWindow->createPie1(map1, "事件类型统计");
        StatisticWindow->createPie2(map2, "日志类型统计");
        StatisticWindow->show();
        tableView->hide();
    });

Just put the map into the function that creates the pie chart. The corresponding map is QMap<label name, quantity>, which is the label on the right side of the pie chart.

        StatisticWindow->createPie1(map1, "事件类型统计");
        StatisticWindow->createPie2(map2, "日志类型统计");

This will create a pie chart

Guess you like

Origin blog.csdn.net/qq_44667165/article/details/133384389