前言
本篇通过提升法实现一个动态圆形进度条。
一、需求
自定义实现一个动态圆形进度条,支持设置进度条颜色、目标值背景色、外边框背景色、中央圆环背景色、旋转角度及大小自适应缩放。同时,支持设置范围值和单位,满足不同场景需要。
效果如下:
二、实现
1、自定义控件类
新建一个自定义控件类,类名为RoundPlot,继承于QWidget类,该类主要负责实现自定义控件。
核心代码如下:
void RoundPlot::drawDial(QPainter *painter)
{
int radius = 95;
double lineWidth = 2.5;
painter->save();
painter->rotate(angle);
//根据起始旋转的角度计算每次坐标需要旋转的角度,按照100等分计算
//每次旋转的角度=360-(起始角度*2--分左右)/100
double rotate = (double)(360 - (angle * 2)) / 100;
//绘制已使用百分比
painter->setPen(QPen(usedColor, lineWidth));
for (double i = 0; i < currentPercent; i++) {
painter->drawLine(0, radius, 0, radius / 1.2);
painter->rotate(rotate);
}
//绘制未使用百分比
painter->setPen(QPen(freeColor, lineWidth));
for (double i = currentPercent; i < 100; i++) {
painter->drawLine(0, radius, 0, radius / 1.2);
painter->rotate(rotate);
}
painter->restore();
}
void RoundPlot::drawBgOut(QPainter *painter)
{
int radius = 70;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(outBgColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void RoundPlot::drawBgRound(QPainter *painter)
{
int radius = 50;
painter->save();
QConicalGradient conicalGradient(radius, radius, 90);
conicalGradient.setColorAt(0, centerBgColorStart);
conicalGradient.setColorAt(1.0, centerBgColorEnd);
painter->setPen(Qt::NoPen);
painter->setBrush(conicalGradient);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void RoundPlot::drawBgCenter(QPainter *painter)
{
int radius = 30;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(valueBgColor);
painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter->restore();
}
void RoundPlot::drawText(QPainter *painter)
{
int radius = 100;
painter->save();
//绘制百分比文字及范围值文字
double currentValue = currentPercent * ((maxValue - minValue) / 100) + minValue;
//如果当前值超过了目标值则取目标值
if (currentValue > value) {
currentValue = value;
}
QString strValue = QString("%1%2").arg(QString::number(currentValue, 'f', precision)).arg(unit);
QString strMinValue = QString("%1%2").arg(minValue).arg(unit);
QString strMaxValue = QString("%1%2").arg(maxValue).arg(unit);
painter->setFont(QFont("Arial", 13));
painter->setPen(QPen(valueTextColor));
QFontMetricsF fm = QFontMetricsF(painter->font());
QSizeF size = fm.size(Qt::TextSingleLine, strValue);
painter->drawText(-size.width() / 2, size.height() / 3, strValue);
painter->setFont(QFont("Arial", 8));
painter->setPen(QPen(rangeTextColor));
fm = QFontMetricsF(painter->font());
size = fm.size(Qt::TextSingleLine, strMinValue);
painter->drawText(-radius / 2 - size.width() / 2 + 8, 80, strMinValue);
size = fm.size(Qt::TextSingleLine, strMaxValue);
painter->drawText(radius / 2 - size.width() / 2 - 8, 80, strMaxValue);
painter->restore();
}
2、提升
在设计师中,将widget控件提升为RoundPlot,如下:
3、效果
编译运行后,效果如下: