Qt沙漏进度和水波进度发布(重写Qwidget实现)
https://blog.****.net/li491093957/article/details/61204422
Qwidget很强大可以重写任何东西。不信我会让你相信。
话不多说来张图片大家就知道了:
心动吗?我们一起来看看。
首先是沙漏进度代码:
-
#ifndef NPROGRESANDCLOCK_H
-
#define NPROGRESANDCLOCK_H
-
#include <QWidget>
-
#include <QTimer>
-
#include <QRect>
-
#include <QPainter>
-
#include <QPaintEvent>
-
#include <QSize>
-
class NProgreSandClock : public QWidget
-
{
-
Q_OBJECT
-
public:
-
NProgreSandClock(QWidget *parent);
-
//设置沙漏外壁的宽
-
void setSandClockWidth(int width);
-
//设置是否循环旋转
-
void setLoop(bool isLoop);
-
//设置沙漏外边的颜色
-
void setSandClockColor(QColor color);
-
//设置沙的颜色
-
void setSandColor(QColor color);
-
//设置沙漏下去速度(毫秒)
-
void setSandDownSpeed(int mes);
-
//设置沙漏旋转的速度(毫秒)
-
void setSandClockRoteSpeed(int mes);
-
//设置当前进度
-
void setSandClockProgre(int progre);
-
~NProgreSandClock();
-
protected:
-
//重绘事件
-
void paintEvent(QPaintEvent *);
-
private:
-
int m_nNowProgres;
-
//设置沙漏外壁的宽
-
int m_nSandClockWidth;
-
//沙漏旋转的速度
-
int m_nSandColorRoteSpeed;
-
//设置沙落下的速度
-
int m_nSandDowSpeed;
-
//沙的颜色
-
QColor m_SandColor;
-
//沙漏颜色
-
QColor m_sandClockColor;
-
//画沙漏
-
void drawSandClock(QPainter* painter);
-
bool isLoop;
-
//旋转沙漏定时器
-
QTimer* m_updateTimer;//定时器时间
-
bool isFirstRotate;
-
//旋转角度
-
qreal m_angle;
-
//外半径
-
qreal m_outerRadius;
-
//记录现在的状态
-
int m_nNowStatus;
-
//是否在画三角形
-
bool isDrawTri;
-
//记录三角形的高
-
qreal triHeight;
-
//现在的状态
-
enum
-
{
-
DRAW_UP_TRIANG=0,DRAW_DOWN_TRIANG,DRAW_CIR_ROTETE
-
};
-
signals:
-
void onProgres(int);
-
private slots:
-
//自定义槽,更新角度旋转
-
void UpdateAngle();
-
};
-
#endif // NPROGRESANDCLOCK_H
沙漏进度CPP:
-
#include "NProgreSandClock.h"
-
NProgreSandClock::NProgreSandClock(QWidget *parent)
-
: QWidget(parent)
-
,m_nNowStatus(2)
-
,isLoop(true),
-
m_angle(0),
-
m_outerRadius(0),
-
isDrawTri(false)
-
,m_sandClockColor(QColor(63,107,157,255))
-
,m_SandColor(QColor(224,143,36,255))
-
,m_nSandDowSpeed(5)
-
,m_nSandColorRoteSpeed(2)
-
,m_nSandClockWidth(4)
-
{
-
//无窗体
-
setWindowFlags(Qt::FramelessWindowHint);
-
//背景透明
-
setAttribute(Qt::WA_TranslucentBackground);
-
m_updateTimer = new QTimer(this);
-
//间隔,微妙微单位,大家可以改一下这个值看看转动速度。
-
m_updateTimer->setInterval(m_nSandColorRoteSpeed);
-
connect(m_updateTimer,SIGNAL(timeout()),this,SLOT(UpdateAngle()));
-
//启动定时器
-
m_updateTimer->start();
-
}
-
//重绘事件
-
void NProgreSandClock::paintEvent(QPaintEvent *event)
-
{
-
QPainter painter(this);
-
painter.setRenderHints(QPainter::Antialiasing|QPainter::HighQualityAntialiasing);//设置反锯齿
-
drawSandClock(&painter);//画沙漏
-
}
-
//画沙漏和三角形
-
void NProgreSandClock::drawSandClock(QPainter *painter)
-
{
-
m_outerRadius = width() > height() ? (qreal)height()/2 : (qreal)width()/2;
-
if (m_nNowStatus== DRAW_CIR_ROTETE)
-
{
-
triHeight=m_outerRadius;
-
}
-
painter->save();
-
// move to center
-
painter->translate(m_outerRadius,m_outerRadius);
-
painter->setPen(QPen(m_sandClockColor,m_nSandClockWidth,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
-
//旋转
-
painter->rotate(m_angle);
-
QRect widgetRect =this->rect();
-
QPainterPath sandClockPath;
-
sandClockPath.moveTo(-m_outerRadius*0.05,m_outerRadius*0.05);
-
sandClockPath.lineTo(m_outerRadius*0.1,m_outerRadius);
-
sandClockPath.lineTo(m_outerRadius,m_outerRadius*0.1);
-
sandClockPath.lineTo(m_outerRadius*0.05,-m_outerRadius*0.05);
-
sandClockPath.lineTo(-m_outerRadius*0.1,-m_outerRadius);
-
sandClockPath.lineTo(-m_outerRadius,-m_outerRadius*0.1);
-
sandClockPath.lineTo(-m_outerRadius*0.05,m_outerRadius*0.05);
-
painter->drawPath(sandClockPath);
-
painter->setPen(Qt::NoPen);
-
if (isLoop)
-
{
-
emit onProgres(-1);
-
QPoint triangle[3];
-
painter->setBrush(QBrush(m_SandColor,Qt::SolidPattern));//设置画刷形式
-
if (m_nNowStatus==DRAW_UP_TRIANG)
-
{
-
if (isDrawTri)
-
{
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(-triHeight*0.1,-triHeight);
-
triangle[2]=QPoint(-triHeight,-triHeight*0.1);
-
triHeight-=1;
-
painter->drawPolygon(triangle,3);
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint((m_outerRadius*0.1)-triHeight*0.1,m_outerRadius-triHeight);
-
triangle[2]=QPoint(m_outerRadius-triHeight,(m_outerRadius*0.1)-triHeight*0.1);
-
if (triHeight<0)
-
{
-
isDrawTri=false;
-
triHeight=m_outerRadius;
-
m_nNowStatus= DRAW_CIR_ROTETE;
-
m_angle+=1;
-
}
-
painter->drawPolygon(triangle,3);
-
}
-
}
-
else if(m_nNowStatus==DRAW_DOWN_TRIANG)
-
{
-
if (isDrawTri)
-
{
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(triHeight*0.1,triHeight);
-
triangle[2]=QPoint(triHeight,triHeight*0.1);
-
triHeight-=1;
-
painter->drawPolygon(triangle,3);
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(-(m_outerRadius*0.1)+triHeight*0.1,-m_outerRadius+triHeight);
-
triangle[2]=QPoint(-m_outerRadius+triHeight,-(m_outerRadius*0.1)+triHeight*0.1);
-
if (triHeight<=0)
-
{
-
isDrawTri=false;
-
triHeight=m_outerRadius;
-
m_nNowStatus= DRAW_CIR_ROTETE;
-
m_angle+=1;
-
}
-
painter->drawPolygon(triangle,3);
-
}
-
}
-
else
-
{
-
if(m_angle>45&&m_angle<=225)
-
{
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(m_outerRadius*0.1-m_nSandClockWidth/3,m_outerRadius-m_nSandClockWidth/3);
-
triangle[2]=QPoint(m_outerRadius-m_nSandClockWidth/3,m_outerRadius*0.1-m_nSandClockWidth/3);
-
}
-
else
-
{
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(-m_outerRadius*0.1+m_nSandClockWidth/3,-m_outerRadius+m_nSandClockWidth/3);
-
triangle[2]=QPoint(-m_outerRadius+m_nSandClockWidth/3,-m_outerRadius*0.1+m_nSandClockWidth/3);
-
}
-
painter->drawPolygon(triangle,3);
-
}
-
}
-
else
-
{
-
qreal nTriHeight=((float)(m_nNowProgres/100.0)*triHeight);
-
emit onProgres(m_nNowProgres);
-
painter->setBrush(QBrush(m_SandColor,Qt::SolidPattern));//设置画刷形式
-
QPoint triangle[3];
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(nTriHeight*0.1,nTriHeight);
-
triangle[2]=QPoint(nTriHeight,nTriHeight*0.1);
-
painter->drawPolygon(triangle,3);
-
triangle[0]=QPoint(0,0);
-
triangle[1]=QPoint(-(m_outerRadius*0.1)+nTriHeight*0.1,-m_outerRadius+nTriHeight);
-
triangle[2]=QPoint(-m_outerRadius+nTriHeight,-(m_outerRadius*0.1)+nTriHeight*0.1);
-
painter->drawPolygon(triangle,3);
-
}
-
painter->restore();
-
}
-
//更新画面
-
void NProgreSandClock::UpdateAngle()
-
{
-
if ((m_angle==45) )
-
{
-
m_nNowStatus=DRAW_UP_TRIANG;
-
m_updateTimer->start(m_nSandDowSpeed);
-
isDrawTri=true;
-
}
-
else if (m_angle==225)
-
{
-
m_nNowStatus=DRAW_DOWN_TRIANG;
-
m_updateTimer->start(m_nSandDowSpeed);
-
isDrawTri=true;
-
}
-
else
-
{
-
m_nNowStatus= DRAW_CIR_ROTETE;
-
m_updateTimer->setInterval(m_nSandColorRoteSpeed);
-
}
-
if (!isDrawTri)
-
{
-
m_angle += 1;
-
if(m_angle > 360)
-
{
-
m_angle = 0;
-
}
-
}
-
//刷新控件,会调用paintEvent函数
-
update();
-
}
-
NProgreSandClock::~NProgreSandClock()
-
{
-
m_updateTimer->stop();
-
}
-
//设置是否循环
-
void NProgreSandClock::setLoop(bool isLoop)
-
{
-
this->isLoop=isLoop;
-
}
-
//设置沙漏颜色
-
void NProgreSandClock::setSandClockColor(QColor color)
-
{
-
this->m_sandClockColor= color;
-
}
-
//设置沙的颜色
-
void NProgreSandClock::setSandColor(QColor color)
-
{
-
this->m_SandColor = color;
-
}
-
//设置沙下降的速度
-
void NProgreSandClock::setSandDownSpeed(int mes)
-
{
-
this->m_nSandDowSpeed=mes;
-
}
-
//设置沙漏旋转的速度
-
void NProgreSandClock::setSandClockRoteSpeed(int mes)
-
{
-
this->m_nSandColorRoteSpeed= mes;
-
}
-
//设置沙漏的宽度
-
void NProgreSandClock::setSandClockWidth(int width)
-
{
-
this->m_nSandClockWidth=width;
-
}
-
//设置当前进度
-
void NProgreSandClock::setSandClockProgre(int progre)
-
{
-
this->m_nNowProgres = progre;
-
if (progre>100)
-
{
-
this->m_nNowProgres=100;
-
}
-
m_angle = 45;
-
m_updateTimer->stop();
-
isLoop = false;
-
update();
-
}
首先沙漏进度还是很简单的:那么再来看看水波进度:
-
#ifndef NPROGRECIRWATER_H
-
#define NPROGRECIRWATER_H
-
#define WATER_HEIGHT 0.06
-
#include <QWidget>
-
#include <math.h>
-
#include <QPainter>
-
#include <QPixmap>
-
#include <QTimer>
-
#include <QFont>
-
class NProgreCirWater : public QWidget
-
{
-
Q_OBJECT
-
public:
-
NProgreCirWater(QWidget *parent);
-
~NProgreCirWater();
-
void setWaterProgre(int progre);
-
protected:
-
void paintEvent(QPaintEvent *event);
-
private:
-
int m_nNowProgre;
-
QTimer m_ChangeWaterTimer;
-
float m_fPy;
-
void createShader(QPainter &painter);
-
QTimer m_TUpGuiimer;
-
// 水波进度
-
float DEFAULT_LEVEL_RATIO ;
-
// 水波高度
-
float DEFAULT_AMPLITUDE_RATIO ;
-
private slots:
-
//自动增加
-
void upAutoTime();
-
//让波浪动起来
-
void upGuiOutTimer();
-
};
-
#endif // NPROGRECIRWATER_H
再来看看实现代码CPP:
-
#include "NProgreCirWater.h"
-
#include "QTool.h"
-
#define M_PI 3.14159265358979323846
-
NProgreCirWater::NProgreCirWater(QWidget *parent)
-
: QWidget(parent),m_fPy(0)
-
{
-
// 水波进度
-
DEFAULT_LEVEL_RATIO = 1.0f;
-
// 水波高度
-
DEFAULT_AMPLITUDE_RATIO = 0;
-
connect(&m_ChangeWaterTimer,SIGNAL(timeout()),this,SLOT(upAutoTime()));
-
connect(&m_TUpGuiimer,SIGNAL(timeout()),this,SLOT(upGuiOutTimer()));
-
m_TUpGuiimer.start(10);
-
m_ChangeWaterTimer.start(90);
-
}
-
NProgreCirWater::~NProgreCirWater()
-
{
-
}
-
void NProgreCirWater::createShader(QPainter &painter) {
-
painter.setRenderHints(QPainter::Antialiasing|QPainter::HighQualityAntialiasing);//设置反锯齿
-
int height = this-> height();
-
int width = this->width();
-
// ω周期 让一个周期的宽度正好是width
-
double frequency = 3 * M_PI / width;
-
// A振幅 默认的振幅是高度的0.05f
-
float amplitude = height * DEFAULT_AMPLITUDE_RATIO;
-
// k(y轴偏移量,进度) 默认的进度是50%
-
float level = height * DEFAULT_LEVEL_RATIO;
-
QPixmap waveBitmap (width,height);
-
QPainter drawWaterPainter(&waveBitmap);
-
drawWaterPainter.setPen(Qt::NoPen);
-
drawWaterPainter.setBrush(Qt::red);
-
QPainterPath abovePath ;
-
QPainterPath behindPath ;
-
abovePath.moveTo(0, height);
-
behindPath.moveTo(0, height);
-
m_fPy+=0.05;
-
if (m_fPy>(width/2))
-
{
-
m_fPy = 0;
-
}
-
for(int x = 0; x<=width; x++) {
-
// y=Asin(ωx+φ)+k
-
float aboveY = (float) (amplitude * sin(frequency * x+m_fPy))+ level;
-
// 背面的水波偏移一些,和前面的错开。
-
float behindY = (float) (amplitude * sin(frequency * x+width/4*frequency+m_fPy ))+ level;
-
abovePath.lineTo(x , aboveY);
-
behindPath.lineTo(x, behindY);
-
}
-
abovePath.lineTo(width+ 1, height);
-
behindPath.lineTo(width+1, height);
-
drawWaterPainter.setBrush(QColor(169,245,233,255));
-
drawWaterPainter.drawPath(behindPath);
-
drawWaterPainter.setBrush(QColor(40,230,200,255));
-
drawWaterPainter.drawPath(abovePath);
-
int nFontSize = width/6;
-
QFont font;
-
font.setPixelSize(nFontSize);
-
drawWaterPainter.setFont(font);
-
drawWaterPainter.setPen(QPen(Qt::white));
-
int nNowPro =100 - (int)(DEFAULT_LEVEL_RATIO*100);
-
QString strProgre = QString::number(nNowPro);
-
strProgre.append("%");
-
drawWaterPainter.drawText(width/2-(nFontSize/2-2),height/2+nFontSize/2,strProgre);
-
drawWaterPainter.end();
-
waveBitmap=QTool::QPixmapToRound(waveBitmap,(float)100);
-
painter.drawPixmap(0,0,waveBitmap);
-
}
-
//重绘事件
-
void NProgreCirWater::paintEvent(QPaintEvent *event)
-
{
-
QPainter painter(this);
-
createShader(painter);
-
QWidget::paintEvent(event);
-
}
-
void NProgreCirWater::upGuiOutTimer()
-
{
-
update();
-
}
-
void NProgreCirWater::upAutoTime()
-
{
-
// 水波高度
-
if (DEFAULT_LEVEL_RATIO<=0)
-
{
-
DEFAULT_LEVEL_RATIO=1;
-
DEFAULT_AMPLITUDE_RATIO=0;
-
}
-
DEFAULT_LEVEL_RATIO-=0.01;
-
DEFAULT_AMPLITUDE_RATIO= (1-DEFAULT_LEVEL_RATIO) * 0.15;
-
if (DEFAULT_AMPLITUDE_RATIO>WATER_HEIGHT)
-
{
-
DEFAULT_AMPLITUDE_RATIO =WATER_HEIGHT;
-
}
-
}
-
void NProgreCirWater::setWaterProgre(int progre)
-
{
-
this->m_nNowProgre = progre;
-
m_ChangeWaterTimer.stop();
-
DEFAULT_LEVEL_RATIO =1.0 - ((float)this->m_nNowProgre) /100.0;
-
DEFAULT_AMPLITUDE_RATIO= (1-DEFAULT_LEVEL_RATIO) * 0.15;
-
if (DEFAULT_AMPLITUDE_RATIO>WATER_HEIGHT)
-
{
-
DEFAULT_AMPLITUDE_RATIO =WATER_HEIGHT;
-
}
-
update();
-
}
下面是调用代码:
-
resize(800,800);
-
NImageButton *pNImageButton = new NImageButton(this);
-
pNImageButton->setGeometry(10,10,120,35);
-
pNImageButton->setMinimumSize(120,35);
-
QPixmap pp("Image/button.png");
-
QPixmap ppc("Image/button1.png");
-
pNImageButton->setNormalImage(pp);
-
pNImageButton->setPressImage(ppc);
-
pNImageButton->setImageArc(10);
-
NProgreCirWater *pNCirProgreWater=new NProgreCirWater(this);
-
pNCirProgreWater->setWaterProgre(35);
-
pNCirProgreWater->setGeometry(110,10,200,200);
-
pNCirProgreWater->setMinimumSize(200,200);
-
NProgreCirWater *pNCirProgreWater1=new NProgreCirWater(this);
-
//pNCirProgreWater1->setWaterProgre(35);
-
pNCirProgreWater1->setGeometry(330,10,200,200);
-
pNCirProgreWater1->setMinimumSize(200,200);
-
NProgreSandClock * pCirProgreWater=new NProgreSandClock(this);
-
pCirProgreWater->setSandDownSpeed(10);
-
pCirProgreWater->setSandClockProgre(35);
-
pCirProgreWater->setSandColor(QColor(Qt::red));
-
pCirProgreWater->setGeometry(110,220,200,100);
-
pCirProgreWater->setMinimumSize(200,200);
-
NProgreSandClock * pCirProgreWater1=new NProgreSandClock(this);
-
pCirProgreWater1->setSandDownSpeed(10);
-
// pCirProgreWater1->setSandClockProgre(35);
-
pCirProgreWater1->setSandColor(QColor(Qt::red));
-
pCirProgreWater1->setGeometry(330,220,100,100);
-
pCirProgreWater1->setMinimumSize(200,200);
好了还是那句老话,学如逆水行舟不进则退。