最近联想电脑管家进行了更新,看到界面上有个类似水波的圆形百分比进度条非常nice,就想自己尝试实现一个,效果如图:
主要是利用QTimer来进行水波更新以达到最终效果,核心代码如下:
void WaterProgressBar::drawProgress(QPainter *painter)
{
int height = this-> height();
int width = this->width();
int side = qMin(width, height);
//start and end
int borderWidth = this->borderWidth + this->borderPadding;
int startX = borderWidth;
int startY = borderWidth;
int endX = width - borderWidth;
int endY = height - borderWidth;
//calculate circle area
side = side - borderWidth * 2;
startX = (width - side) / 2;
startY = (height - side) / 2;
endX = (width + side) / 2;
endY = (height + side) / 2;
//calculate current value's percent
double percent = 1 - (double)(value - minValue) / (maxValue - minValue);
//formula: y = A * qSin(ωx + φ) + k
//w表示周期,可以理解为水波的密度,值越大密度越大(浪越密集 ^_^),取值 密度*M_PI/宽度
double w = waterDensity * M_PI / endX;
//A表示振幅,可以理解为水波的高度,值越大高度越高(越浪 ^_^),取值高度的百分比
double A = endY * waterHeight;
//k表示y轴偏移,可以理解为进度,取值高度的进度百分比
double k = endY * percent;
//calculate circle area
k = (side * percent) + startY;
//first wave PainterPath
QPainterPath waterPath1;
//second wave PainterPath
QPainterPath waterPath2;
//move to start
waterPath1.moveTo(startX, endY);
waterPath2.moveTo(startX, endY);
offset += 0.6;
if (offset > (endX / 2)) {
offset = 0;
}
for(int x = startX; x <= endX; x++) {
//first wave YAxis
double waterY1 = (double)(A * qSin(w * x + offset)) + k;
//second wave YAxis
double waterY2;
if (reverse) {
waterY2 = (double)(A * qSin(w * -x + offset + 10)) + k;
} else {
waterY2 = (double)(A * qSin(w * x + offset + (endX / 2 * w))) + k;
}
//如果当前值为最小值则Y轴为右下角Y轴
if (this->value == minValue) {
waterY1 = endY;
waterY2 = endY;
}
//如果当前值为最大值则Y轴为右上角Y轴
if (this->value == maxValue) {
waterY1 = startY;
waterY2 = startY;
}
waterPath1.lineTo(x, waterY1);
waterPath2.lineTo(x, waterY2);
}
//end the PainterPath
waterPath1.lineTo(endX, endY);
waterPath2.lineTo(endX, endY);
//border
QPainterPath bigPath;
bigPath.addEllipse(startX, startY, side, side);
//get new waves path
QPainterPath path;
QColor waterColor1 = usedColor;
waterColor1.setAlpha(100);
QColor waterColor2 = usedColor;
waterColor2.setAlpha(200);
painter->save();
painter->setPen(Qt::NoPen);
//first wave intersected
path = bigPath.intersected(waterPath1);
painter->setBrush(waterColor1);
painter->drawPath(path);
//second wave intersected
path = bigPath.intersected(waterPath2);
painter->setBrush(waterColor2);
painter->drawPath(path);
painter->restore();
}
全套代码链接:🍞正在为您运送作品详情