使用QPainter绘制饼状图,并显示所占百分比

绘制饼状图qt就有现成的函数来用,要在相应部分的弧形里显示百分比就需要做一点处理。

做法就是在获取扇形二等分线的中点坐标,以这个中点坐标为中心的一个区域再绘制文字。

获取中点坐标使用三角函数即可,半径懂,角度也有,很容易就算出距离,再根据所在的象限添加符号就是坐标了

效果图:


下面上代码

头文件

#include <QWidget>
#include <QPainter>
#include <QMap>

class ArcWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ArcWidget(QWidget *parent = 0);
    ~ArcWidget();

protected:
    void paintEvent(QPaintEvent *e);

private:
    QString getPercentInt(const QString &percentStr);


private:
    QMap<QString, int> m_answerMap;
    QList<int> m_numList;
    QList<QString> m_answerStrList;
    int m_nPeopleCount;
    qreal m_pi = 3.1415;

};

cpp文件

#include "arcwidget.h"

ArcWidget::ArcWidget(QWidget *parent)
    : QWidget(parent), m_nPeopleCount(0)
{
    this->resize(600, 600);

    m_answerMap.insert("A", 3);
    m_answerMap.insert("B", 5);
    m_answerMap.insert("C", 8);
    m_answerMap.insert("D", 2);

    m_answerStrList = m_answerMap.keys();
    m_numList = m_answerMap.values();
    foreach (int num, m_numList) {
        m_nPeopleCount += num;
    }
}

ArcWidget::~ArcWidget()
{

}

void ArcWidget::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::NoBrush);
//    painter.drawImage(this->rect(),m_bg);

    QRectF rect(-120, -120,
                (120 << 1), (120 << 1));
    QList<QColor> colorList;

    painter.translate(220, 255);
    qreal startAngle = 0;
    foreach (int num, m_numList) {

        //生成随机颜色并过滤掉白色
        int colorR, colorG, colorB;
        while(1)
        {
            colorR = rand()%256;
            colorG = rand()%256;
            colorB = rand()%256;

            if(colorR == 255 && colorG == 255 && colorB == 255)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        QColor color(colorR, colorG, colorB);
        colorList.append(color);

        painter.setPen(Qt::NoPen);
        painter.setBrush(QBrush(color));

        //该答案选项所占比例
        qreal percentNum = (qreal)num/(qreal)m_nPeopleCount;
        //所占比例对应的角度
        qreal arcLength = 360*percentNum;

        //画扇形
        QPainterPath path;
        path.arcTo(rect, startAngle, arcLength);

        //扇形二等分线的角度
        qreal middleAngle = startAngle + arcLength/2;
        qreal radianNum = 0;
        if(middleAngle >= 0 && middleAngle < 90)
        {
            radianNum = middleAngle*m_pi/180;
        }
        else if(middleAngle >= 90 && middleAngle < 180)
        {
            radianNum = (180 - middleAngle)*m_pi/180;
        }
        else if(middleAngle >= 180 && middleAngle < 270)
        {
            radianNum = (middleAngle - 180)*m_pi/180;
        }
        else if(middleAngle >= 270 && middleAngle < 360)
        {
            radianNum = (360 - middleAngle)*m_pi/180;
        }

        //二等分线的中点距原点的距离
        qreal textPosY = 60*sin(radianNum);
        qreal textPosX = 60*cos(radianNum);

        //根据二等分线所在的象限确定二等分线的中点坐标
        if(middleAngle >= 0 && middleAngle < 90)
        {
            textPosY = -textPosY;
        }
        else if(middleAngle >= 90 && middleAngle < 180)
        {
            textPosX = -textPosX;
            textPosY = -textPosY;
        }
        else if(middleAngle >= 180 && middleAngle < 270)
        {
            textPosX = -textPosX;
        }

        startAngle += arcLength;
        QString percentStr = QString::number(percentNum*100 + 0.5);
        percentStr = getPercentInt(percentStr) + "%";
        painter.drawPath(path);
        painter.setPen(QColor(Qt::white));
        painter.drawText(textPosX - 25, textPosY -10,
                         50, 20, Qt::AlignCenter, percentStr);

    }

    painter.setBrush(Qt::NoBrush);
    painter.setPen(QColor(0, 0, 0));
    painter.translate(-220, -255);

    //绘制右侧的标注栏
    QFont ft;
    ft.setPixelSize(15);
    painter.setFont(ft);
    int textStart = 140;
    foreach (QString answerStr, m_answerStrList) {
        painter.drawText(350, textStart,
                         40, 16,
                         Qt::AlignRight, answerStr);
        textStart += 30;
    }

    textStart = 143;
    painter.setPen(Qt::NoPen);
    foreach (QColor color, colorList) {
        painter.setBrush(QBrush(color));
        painter.drawRect(402, textStart, 15, 15);
        textStart += 30;
    }

    QWidget::paintEvent(e);
}

QString ArcWidget::getPercentInt(const QString &percentStr)
{
    QString percentIntStr;
    for(int i = 0;i < percentStr.size();++i)
    {
        if(percentStr.at(i) == '.')
        {
            break;
        }
        percentIntStr += percentStr.at(i);
    }

    return percentIntStr;
}

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值