QPainter to draw a pie chart

FIG effect
Pattern 1:
Here Insert Picture Description
Pattern 2:
Here Insert Picture Description

head File

#ifndef QWHPIE_H
#define QWHPIE_H

#include <QWidget>
#include <QPaintEvent>
#include <QPainter>

class QWHPie : public QWidget
{
    Q_OBJECT
public:
    enum LegendAlign
    {
        LegendAlign_Bottom, //图例在底部
        LegendAlign_Right,  //图例在右侧
    };

    struct PieData
    {
      QString name; //名称
      double percent;  //百分比
      QColor color; //颜色

      PieData(QString name, double percent, QColor color){
          this->name = name;
          this->percent = percent;
          this->color = color;
      }
    };

    explicit QWHPie(QWidget *parent = nullptr);

    void setPieDatas(QList<PieData> pieDatas, int columnCount);
    void addPieData(PieData pieData, int index);
    void removePieData(int index);
protected:
    void paintEvent(QPaintEvent *event);
    void drawTitle(QPainter *painter);
    void drawName(QPainter *painter);
    void drawPie(QPainter *painter);
    void drawLegend(QPainter *painter);
private:
    double degreeToRadius(double degree);
signals:

public slots:

private:
    bool m_showTitle;           //是否显示标题
    QString m_title;            //标题名称
    int m_titleHeight;          //标题高度
    QColor m_tileColor;         //标题颜色

    bool m_showLegend;          //是否显示图例
    int m_legendHeight;         //图例高度
    int m_legendWidth;          //图例宽度
    int m_legendColumnCount;    //图例列数
    int m_legendCount;          //图列数量
    LegendAlign m_legendAlign;  //图例位置
    int m_margin;               //图例边距
    QColor m_legendNameColor;   //图例名称颜色

    bool m_showPieMargin;       //饼图各模块连接是否有缝隙
    QColor m_pieMarginColor;    //饼图边缘颜色
    float m_pieDataRadius;      //饼图数据距中心点距离

    QList<PieData> m_PieDatas;  //饼图数据集合
};

#endif // QWHPIE_H

Core code

void QWHPie::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //绘制标题
    drawTitle(&painter);    
    //绘制饼图
    drawPie(&painter);
    //绘制饼图文字(百分比前面的具体内容)
    //drawName(&painter);
    //绘制图例
    drawLegend(&painter);
}

void QWHPie::drawTitle(QPainter *painter)
{
    painter->save();

    QRect rect(0, 0, this->width(), m_titleHeight);
    painter->drawText(rect, Qt::AlignCenter, m_title);

    painter->restore();
}
   
void QWHPie::drawPie(QPainter *painter)
{
    painter->save();

    int width = this->width();
    int height = this->height();
    painter->setPen(Qt::white);

    int legendRows = 0;

    if (m_legendAlign == LegendAlign_Bottom)
    {
        legendRows = qCeil(m_legendCount * 1.0 / m_legendColumnCount);
        QRect rect(0, m_titleHeight, width, height - m_titleHeight - legendRows * m_legendHeight);
        painter->translate(rect.center());
        int side = qMin(rect.width(), rect.height());
        painter->scale(side / 100, side / 100);
    }
    else if (m_legendAlign == LegendAlign_Right)
    {
        QRect rect(0, m_titleHeight, width - m_legendColumnCount * m_legendWidth, height - m_titleHeight);
        painter->translate(rect.center());
        int side = qMin(rect.width(), rect.height());
        painter->scale(side / 100, side / 100);
    }

    int radius = 49;
    double startAngle = 0;
    QRect rect = QRect(-radius, -radius, 2 * radius, 2 * radius);

    for (int i = 0; i < m_legendCount; i++)
    {
        //绘制扇形区域
        double angle = m_PieDatas.at(i).percent * 1.0 / 100 * 360;
        painter->setPen(Qt::white);
        painter->setBrush(m_PieDatas.at(i).color);
        painter->drawPie(rect, startAngle * 16, angle * 16);
        //绘制扇区文本
        int textAngle = (startAngle + (startAngle + angle)) / 2;
        int x = radius * m_pieDataRadius * qCos(degreeToRadius(textAngle));
        int y = radius * m_pieDataRadius * qSin(degreeToRadius(textAngle));

        QFont font;
        font.setPixelSize(5);
        painter->setFont(font);
        QRectF textRect = QRectF(x - radius, -y - radius, 2 * radius, 2 * radius);
        QString text = QString("%1%").arg(m_PieDatas.at(i).percent);
        painter->setPen(Qt::black);
        painter->drawText(textRect, Qt::AlignCenter, text);
        startAngle += angle;
    }

    painter->restore();
}

void QWHPie::drawLegend(QPainter *painter)
{
    painter->save();

    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    if (m_legendAlign == LegendAlign_Bottom)
    {
        int legendRows = qCeil(m_legendCount * 1.0 / m_legendColumnCount);
        int legendWidth = width / m_legendColumnCount;
        painter->translate(0, height - legendRows * m_legendHeight);

        int rowIndex = 0;
        int columnIndex = 0;
        for (int i = 0; i < m_legendCount; i++)
        {
            int x = columnIndex * legendWidth + m_margin;
            QRect rectLegend(x, rowIndex * m_legendHeight, 0.8 * m_legendHeight, 0.8 * m_legendHeight);
            painter->setPen(m_PieDatas.at(i).color);
            painter->setBrush(m_PieDatas.at(i).color);
            painter->drawRoundedRect(rectLegend, 0.1 * m_legendHeight, 0.1 * m_legendHeight);

            painter->setPen(m_legendNameColor);
            painter->setBrush(m_legendNameColor);
            x = columnIndex * legendWidth + m_margin + m_legendHeight;
            QRect rectText(x, rowIndex * m_legendHeight, legendWidth - m_margin - m_legendHeight, 0.8 * m_legendHeight);
            QString text = QString("%1: %2%").arg(m_PieDatas.at(i).name).arg(m_PieDatas.at(i).percent);
            painter->drawText(rectText, Qt::AlignVCenter | Qt::AlignLeft, text);

            columnIndex++;
            if (columnIndex % m_legendColumnCount == 0)
            {
                columnIndex = 0;
                rowIndex++;
            }
        }
    }
    else if (m_legendAlign == LegendAlign_Right)
    {
        int legendRows = qCeil(m_legendCount * 1.0 / m_legendColumnCount);
        int legendWidth = m_legendWidth;
        int legendHeight = (height - m_titleHeight) / legendRows;
        painter->translate(0, m_titleHeight);

        int rowIndex = 0;
        int columnIndex = 0;
        for (int i = 0; i < m_legendCount; i++)
        {
            int x = (width - m_legendColumnCount * m_legendWidth) + columnIndex * legendWidth + m_margin;
            QRect rectLegend(x, rowIndex * legendHeight, 0.8 * m_legendHeight, 0.8 * m_legendHeight);
            painter->setPen(m_PieDatas.at(i).color);
            painter->setBrush(m_PieDatas.at(i).color);
            painter->drawRoundedRect(rectLegend, 0.1 * m_legendHeight, 0.1 * m_legendHeight);

            x = (width - m_legendColumnCount * m_legendWidth) + columnIndex * legendWidth + m_margin + m_legendHeight;
            QRect rectText(x, rowIndex * legendHeight, legendWidth, 0.8 * m_legendHeight);
            QString text = QString("%1: %2%").arg(m_PieDatas.at(i).name).arg(m_PieDatas.at(i).percent);
            painter->drawText(rectText, Qt::AlignVCenter | Qt::AlignLeft, text);

            columnIndex++;
            if (columnIndex % m_legendColumnCount == 0)
            {
                columnIndex = 0;
                rowIndex++;
            }
        }
    }

    painter->restore();
}
Published 228 original articles · won praise 44 · Views 100,000 +

Guess you like

Origin blog.csdn.net/qq_40945965/article/details/100188614