.h
#ifndef _QROUNDPROGRESSBAR_H_
#define _QROUNDPROGRESSBAR_H_
#include
class QRoundProgressBar : public QWidget
{
Q_OBJECT
//进度条形状
enum BarStyle
{
//圆环状
StyleDonut = 0,
//圆饼状
StylePie,
//圆线状
StyleLine
};
public:
QRoundProgressBar(QWidget *parent , BarStyle style = StyleLine);
~QRoundProgressBar();
public:
//设置扫描弧度起始角度
void setStartAngle(double position);
//设置轮廓画笔的宽度
void setOutlinePenWidth(double penWidth);
//设置画笔宽度
void setDataPenWidth(double penWidth);
//设置进度条精度 88.88%,几位小数
void setDecimals(int count);
//设置进度条风格
void setBarStyle(BarStyle style);
//设置范围
void setRange(double min, double max);
//设置当前值
void setValue(int val);
//设置当前值
void setValue(double val);
//设置最小值
void setMinimum(double min);
//设置最大值
void setMaximum(double max);
protected:
void paintEvent(QPaintEvent *event);
//画基础图形
void drawBase(QPainter& p, const QRectF& baseRect, const QRectF &innerRect);
//根据值画出进度条
void drawValue(QPainter& p, const QRectF& baseRect, double value, double arcLength, const QRectF & innerRect
, double innerDiameter);
//画中心文字
void drawText(QPainter& p, const QRectF& innerRect, double value);
private:
double m_min; //最小值
double m_max; //最大值
double m_value; //当前值
BarStyle m_barStyle; //进度条风格
int m_decimals; //进度条精度
double m_startAngel; //扫描弧度起始角度
double m_outlinePenWidth; //轮廓画笔的宽度
double m_dataPenWidth; //画笔宽度
};
#endif // _QROUNDPROGRESSBAR_H_
.cpp
#include "QRoundProgressBar.h"
#include
#include
#include
QRoundProgressBar::QRoundProgressBar(QWidget *parent , BarStyle style)
: QWidget(parent)
, m_min(0)
, m_max(100)
, m_value(0)
, m_startAngel(90)
, m_barStyle(style)
, m_outlinePenWidth(0)
, m_dataPenWidth(0)
, m_decimals(0)
{
}
QRoundProgressBar::~QRoundProgressBar()
{
}
void QRoundProgressBar::setStartAngle(double angle)
{
if (angle != m_startAngel)
{
m_startAngel = angle;
update();
}
}
void QRoundProgressBar::setOutlinePenWidth(double penWidth)
{
if (penWidth != m_outlinePenWidth)
{
m_outlinePenWidth = penWidth;
update();
}
}
void QRoundProgressBar::setDataPenWidth(double penWidth)
{
if (penWidth != m_dataPenWidth)
{
m_dataPenWidth = penWidth;
update();
}
}
void QRoundProgressBar::setDecimals(int count)
{
if (count >= 0 && count != m_decimals)
{
m_decimals = count;
update();
}
}
void QRoundProgressBar::setBarStyle(BarStyle style)
{
if (style != m_barStyle)
{
m_barStyle = style;
update();
}
}
void QRoundProgressBar::setRange(double min, double max)
{
m_min = min;
m_max = max;
if (m_max < m_min)
{
qSwap(m_max, m_min);
}
if (m_value < m_min)
{
m_value = m_min;
}
else if (m_value > m_max)
{
m_value = m_max;
}
update();
}
void QRoundProgressBar::setValue(double val)
{
if (m_value != val)
{
if (val < m_min)
{
m_value = m_min;
}
else if (val > m_max)
{
m_value = m_max;
}
else
{
m_value = val;
}
update();
}
}
void QRoundProgressBar::setValue(int val)
{
setValue(double(val));
}
void QRoundProgressBar::setMinimum(double min)
{
setRange(min, m_max);
}
void QRoundProgressBar::setMaximum(double max)
{
setRange(m_min, max);
}
void QRoundProgressBar::paintEvent(QPaintEvent* /*event*/)
{
//外圈直径
double outerDiameter = this->width();
//外圈矩形
QRectF baseRect(0, 0, outerDiameter, outerDiameter);
QPainter p(this);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
//画背景矩形填充白色
p.fillRect(baseRect, QBrush(QColor("#FFFFFF")));
//内圆直径
double innerDiameter;
//内圈矩形
QRectF innerRect;
//计算内圈矩形
if (m_barStyle == StyleLine)
{
innerDiameter = outerDiameter - m_outlinePenWidth;
}
else if(m_barStyle == StyleDonut)
{
innerDiameter = outerDiameter * 0.9;
}
double delta = (outerDiameter - innerDiameter) / 2;
innerRect = QRectF(delta, delta, innerDiameter, innerDiameter);
//画基础图形
drawBase(p, baseRect, innerRect);
//计算当前步长比例
double arcStep = 360.0 / (m_max - m_min) * m_value;
//根据值画出进度条
drawValue(p, baseRect, m_value, arcStep, innerRect, innerDiameter);
//画文字
drawText(p, baseRect, m_value);
p.end();
}
void QRoundProgressBar::drawBase(QPainter &p, const QRectF &baseRect, const QRectF &innerRect)
{
switch (m_barStyle)
{
case StyleDonut:
{
QPainterPath dataPath;
dataPath.setFillRule(Qt::OddEvenFill);
dataPath.moveTo(baseRect.center());
dataPath.addEllipse(innerRect);
QPen pen;
pen.setColor(QColor("#DEE3E7"));
pen.setWidth(10);
p.setPen(pen);
p.setBrush(QBrush(QColor("#FFFFFF")));
p.drawPath(dataPath);
break;
}
case StylePie:
{
p.setPen(QPen(QColor("#FFFFFF"), m_outlinePenWidth));
p.setBrush(QBrush(QColor("#DEE3E7")));
p.drawEllipse(baseRect);
break;
}
case StyleLine:
{
p.setPen(QPen(QColor("#FFFFFF"), m_outlinePenWidth));
p.setBrush(Qt::NoBrush);
p.drawEllipse(baseRect.adjusted(m_outlinePenWidth / 2, m_outlinePenWidth / 2, -m_outlinePenWidth / 2, -m_outlinePenWidth / 2));
break;
}
default:
{
break;
}
}
}
void QRoundProgressBar::drawValue(QPainter &p, const QRectF &baseRect , double value, double arcLength
, const QRectF & innerRect, double innerDiameter)
{
if (value == m_min)
{
return;
}
if (m_barStyle == StyleLine)
{
p.setPen(QColor("#2F8DED"));
p.setBrush(Qt::NoBrush);
p.drawArc(baseRect,m_startAngel * 16, -arcLength * 16);
}
else if (m_barStyle == StyleDonut)
{
QPen pen;
pen.setColor(QColor("#2F8DED"));
pen.setWidth(10);
pen.setCapStyle(Qt::RoundCap);
p.setPen(pen);
p.drawArc(innerRect, m_startAngel*16 , -16*arcLength);
}
else
{
//获取中心点坐标
QPointF centerPoint = baseRect.center();
QPainterPath dataPath;
dataPath.setFillRule(Qt::WindingFill);
dataPath.moveTo(centerPoint);
//逆时针画弧长
dataPath.arcTo(baseRect, m_startAngel, -arcLength);
if (m_barStyle == StylePie)
{
dataPath.lineTo(centerPoint);
p.setPen(QPen(QColor("#2F8DED"), m_dataPenWidth));
}
p.setBrush(QBrush(QColor("#2F8DED")));
p.drawPath(dataPath);
}
}
void QRoundProgressBar::drawText(QPainter &p, const QRectF &rect, double value)
{
QString textToDraw = "%";
double percent = (value - m_min) / (m_max - m_min) * 100.0;
textToDraw = QString::number(percent, 'f', m_decimals) + textToDraw;
QFont f;
f.setFamily("微软雅黑");
f.setPixelSize(20);
p.setFont(f);
p.setPen(QColor("#606266"));
p.drawText(rect, Qt::AlignCenter, textToDraw);
}