如下:
步骤(重写paintEvent):
- 将painter移动到中心
- 确定半径为宽高中较小值的一半,防止缩放变形,优先填满较小的那一边
- 绘制底部圆
- 绘制中间的扇形,且画刷采用锥形渐变
- 最顶部的圆
- 绘制文字,且画在最中心
注:每一步都可以开放接口(这里就不加了)将参数暴漏出来,让外部使用者自己设置从而定制这个外观
头文件:
注:里面的set和get方法,还有Q_PPROPERTY都是qt自己加的,点击重构就可以添加
#ifndef ANNULARPROGRESSBAR_H
#define ANNULARPROGRESSBAR_H
#include <QObject>
#include <QWidget>
#include<QPainter>
//环形进度条
class AnnularProgressBar : public QWidget
{
Q_OBJECT
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged FINAL)
Q_PROPERTY(int min READ min WRITE setMin NOTIFY minChanged FINAL)
Q_PROPERTY(int max READ max WRITE setMax NOTIFY maxChanged FINAL)
public:
explicit AnnularProgressBar(QWidget *parent = nullptr);
int value() const;
void setValue(int newValue);
int min() const;
void setMin(int newMin);
int max() const;
void setMax(int newMax);
protected:
void paintEvent(QPaintEvent* ev) override;
private:
int mValue=50;//进度条的当前值
int mMin=0;//最小值
int mMax=100;//最大值
signals:
void valueChanged();
void minChanged();
void maxChanged();
};
#endif // ANNULARPROGRESSBAR_H
cpp文件:
#include "annularprogressbar.h"
AnnularProgressBar::AnnularProgressBar(QWidget *parent)
: QWidget{parent}
{}
void AnnularProgressBar::paintEvent(QPaintEvent *ev)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width()/2,height()/2);//移动到中心
//底部圆的半径、扇形的半径
int r=std::min(width()/2,height()/2)-5;//防止缩放变形,优先填满较小的那一边
//底部圆对应的矩形
QRect rectBottom=QRect(-r,-r,2*r,2*r);
//顶部部圆对应的矩形
QRect rectTop=rectBottom.adjusted(r/5,r/5,-r/5,-r/5);//左上角和右下角往里缩r/5px
//1、先画最底部的圆
painter.save();
painter.setPen(Qt::NoPen);//去掉轮廓
painter.setBrush(Qt::gray);//设置画刷 填充为红色
painter.drawEllipse(rectBottom);
painter.restore();
//2、再画中间表示进度的扇形
painter.save();
painter.setPen(Qt::NoPen);//去掉轮廓
QConicalGradient cg(rectBottom.center(),90);
cg.setColorAt(0,Qt::red);
cg.setColorAt(1,Qt::blue);
painter.setBrush(cg);//设置画刷 为锥形渐变
//起始角度:90度 即0点的位置
//跨越的角度:当前值/值范围 用这个比例*360度,就是对应的角度 前面加-号,变成顺时针画
painter.drawPie(rectBottom,90*16,-mValue*1.0/(mMax-mMin)*360*16);
painter.restore();
//3、绘制顶部的圆
painter.save();
painter.setPen(Qt::NoPen);//去掉轮廓
painter.setBrush(Qt::green);//设置画刷 填充为绿色
painter.drawEllipse(rectTop);
painter.restore();
//4、绘制文字
painter.save();
painter.setPen(Qt::black);
QFont font=painter.font();
font.setPointSize(rectBottom.width()/4);
font.setFamily("黑体");
painter.setFont(font);
//绘制在整个中心
painter.drawText(rectBottom,Qt::AlignCenter,QString("%1%").arg(100*mValue*1.0/(mMax-mMin)));
painter.restore();
}
int AnnularProgressBar::max() const
{
return mMax;
}
void AnnularProgressBar::setMax(int newMax)
{
if (mMax == newMax)
return;
mMax = newMax;
emit maxChanged();
}
int AnnularProgressBar::min() const
{
return mMin;
}
void AnnularProgressBar::setMin(int newMin)
{
if (mMin == newMin)
return;
mMin = newMin;
emit minChanged();
}
int AnnularProgressBar::value() const
{
return mValue;
}
void AnnularProgressBar::setValue(int newValue)
{
if(newValue>mMax)
{
mValue =mMax;
return;
}
if(newValue<mMin)
{
mValue=mMin;
return;
}
if (mValue == newValue)
return;
mValue = newValue;
emit valueChanged();
update();
}
知识点:
- QRect::adjusted快速根据一个矩形进行调整得到另一个矩形
QRect QRect::adjusted(int dx1, int dy1, int dx2, int dy2) const
该成员方法可以快速根据一个矩形进行调整得到另一个矩形
其中dx1,dy1,表示原来矩形的左上角往里或者往外缩多少,都为正,则左上角往里缩,都为负,则左上角往外缩
dx2,dy2,表示原来矩形的右下角往里或者往外缩多少,都为正,则右下角往外缩,都为负,则右下角往里缩
- 锥形渐变
QConicalGradient cg(rectBottom.center(),90);//渐变中心,起始角度(0为3点钟方向,逆时针)
cg.setColorAt(0,Qt::red);
cg.setColorAt(1,Qt::blue);
- 将文本画在矩形的中心Qt::AlignCenter
//绘制文本时指定对齐方式
painter.drawText(rectBottom,Qt::AlignCenter,QString("%1%").arg(100*mValue*1.0/(mMax-mMin)));