Qt沙漏进度和水波进度发布(重写Qwidget实现)

    xiaoxiao2021-03-25  93

    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); 好了还是那句老话,学如逆水行舟不进则退。
    转载请注明原文地址: https://ju.6miu.com/read-24220.html

    最新回复(0)