Qt控件:动态波浪与进度显示
程序员文章站
2022-05-28 20:13:57
...
1. 预览图
2. 代码
头文件
#ifndef WATERPROCESSBAR_H
#define WATERPROCESSBAR_H
#include <QWidget>
#include <QPainter>
#include <QTimer>
#include <QtMath>
class WaterProcessBar : public QWidget
{
Q_OBJECT
public:
explicit WaterProcessBar(QWidget *parent = nullptr);
private:
void drawBg(QPainter *painter);
void drawProcess(QPainter *painter);
void drawValue(QPainter *painter);
void timeout();
private:
QTimer *timer;
QColor m_textColor;
QColor m_borderColor;
QColor m_bgColor;
QColor m_usedColor;
QColor m_usedColor_lowbattery;
int m_value;
int m_minValue;
int m_maxValue;
int m_waterDensity;
double m_waterHeight;
double m_offset;
int m_borderWidth;
protected:
void paintEvent(QPaintEvent *event);
signals:
};
#endif // WATERPROCESSBAR_H
源文件
#include "waterprocessbar.h"
WaterProcessBar::WaterProcessBar(QWidget *parent) : QWidget(parent)
{
m_value = 50;//百分之比变量
m_minValue = 0;
m_maxValue = 100;
m_waterDensity = 10; // 水波的密度
m_waterHeight = 0.07;
m_offset = 50;
m_borderWidth = 10;
m_textColor = Qt::white;
m_borderColor = Qt::black;
m_bgColor = Qt::gray;
m_usedColor = QColor(0,255,127);
m_usedColor_lowbattery = QColor(255,69,0);
timer = new QTimer(this);
timer->start(80);
connect(timer,&QTimer::timeout,this,&WaterProcessBar::timeout);
}
void WaterProcessBar::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
//背景
drawBg(&painter);
//进度、水波
drawProcess(&painter);
//进度数字
drawValue(&painter);
}
void WaterProcessBar::drawBg(QPainter *painter)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height) - m_borderWidth;
int startX = (width - side) * 0.5;
int startY = (height - side) * 0.5;
painter->save();
painter->setBrush(QBrush(m_bgColor));
if (m_borderWidth == 0)
{
painter->setPen(Qt::NoPen);
}
else
{
QBrush brush(m_borderColor);
painter->setPen(QPen(brush, m_borderWidth, Qt::SolidLine));
}
painter->drawEllipse(startX, startY, side, side);
painter->restore();
}
void WaterProcessBar::drawProcess(QPainter *painter)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height) - (2 * m_borderWidth); //直径
int startX = (width - side) * 0.5;
int startY = (height - side) *0.5;
int endX = startX + side;
int endY = startY + side;
double percent = (m_value * 1.0) / (m_maxValue - m_minValue);
double w = 2 * M_PI / endX;
double A = endY * m_waterHeight;
double k = endY * (1.0 - percent);
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(m_usedColor);
QPainterPath totalPath;
//加入圆形路径
totalPath.addEllipse(startX, startY, side, side);
//水波路径
QPainterPath water1;
QPainterPath water2;
water1.moveTo(startX, endY);
water2.moveTo(startX, endY);
m_offset += 0.6;
if (m_offset > (endX / 2)) {
m_offset = 0;
}
for(int i = startX; i < endX; i++) {
//第一条波浪Y轴
double waterY1 = (double)(A * qSin(w * i + m_offset)) + k;
//第二条波浪Y轴
double waterY2;
waterY2 = (double)(A * qSin(w * i + m_offset + (endX / 2 * w))) + k;
water1.lineTo(i, waterY1);
water2.lineTo(i, waterY2);
if (m_value == m_minValue) {
waterY1 = endY;
}
if (m_value == m_maxValue) {
waterY1 = startY;
}
}
//封闭
water1.lineTo(endX, endY);
water2.lineTo(endX, endY);
QPainterPath path;
QColor waterColor1 = (m_value <=30)?m_usedColor_lowbattery:m_usedColor;
waterColor1.setAlpha(100);
QColor waterColor2 = (m_value <=30)?m_usedColor_lowbattery:m_usedColor;
waterColor2.setAlpha(200);
//第一条波浪
path = totalPath.intersected(water1);
painter->setBrush(waterColor1);
painter->drawPath(path);
//第二条波浪挖去后的路径
path = totalPath.intersected(water2);
painter->setBrush(waterColor2);
painter->drawPath(path);
painter->restore();
}
void WaterProcessBar::drawValue(QPainter *painter)
{
painter->save();
int width = this->width();
int height = this->height();
int side = qMin(width, height) - m_borderWidth;
int startX = (width - side) * 0.5;
int startY = (height - side) * 0.5;
int fontSize = side / 4;
QFont font;
font.setFamily("微软雅黑");
font.setPixelSize(fontSize);
font.setBold(true);
painter->setFont(font);
painter->setPen(Qt::white);
painter->drawText(QRectF(startX, startY, side, side), Qt::AlignCenter, QString("%1%").arg(m_value));
painter->restore();
}
void WaterProcessBar::timeout()
{
this->update();
}
3. 用法
-
创建类,然后在创建的头文件和源文件里面添加上述代码
-
在UI界面里面拖拽widget部件
-
将widget部件提升为自定义的类,在提升的类名称里面填入上面源代码里面的类名
-
调用函数如下,在设计师界面类里面调用这个函数即可
void GaugePanel::setValue(int value)
{
setValue(double(value));
}
ui->控件对象名->setValue(a);
上一篇: Android零基础入门第24节:自定义View简单使用
下一篇: Android