自定义控件之水波纹进度条

直接上图,如图所示,在写Qt自带的控件满足不了我们程序的需求时,我们可以自绘空间,利用QPainter的灵活性,绘制各种效果的控件,学习了feiyangqingyun大佬,还有其他博主的思路代码,下面就展示最近的学习成果,水波纹进度条:

主要难点在于三角函数公式中的正弦函数,可以温习一下以前的数学知识。

下面贴上关键代码

waterprogressbar1.cpp
#include "waterprogressbar1.h"
#include "ui_waterprogressbar1.h"
#include<QPainter>
#include<QTimer>
#include<QDebug>
#include<qmath.h>

WaterProgressBar1::WaterProgressBar1(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WaterProgressBar1)
{
    ui->setupUi(this);
    QTimer *timer = new QTimer;
    connect(timer,QTimer::timeout,this,[=](){
        this->offset += 0.6;
        update();
    });
    timer->start(100);
}

WaterProgressBar1::~WaterProgressBar1()
{
    delete ui;
}

void WaterProgressBar1::paintEvent(QPaintEvent *event){
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);


    drawBg(&painter);
    drawE(&painter);
    drawWater(&painter);
    drawText(&painter);

}

void WaterProgressBar1::updateValue(float va){
    this->value = va;
    update();
}

void WaterProgressBar1::setSinA(float sinA){
    this->sinA = sinA;
    update();
}

void WaterProgressBar1::setSinAlph(float alph){
    this->sinAlph = alph;
    update();
}

void WaterProgressBar1::setOffset(float set){
    this->offset = set;
    update();
}

void WaterProgressBar1::setWaterColor(QColor color){
    waterColor = color;
    update();
}

float WaterProgressBar1::getSinA(){
    return sinA;
}

float WaterProgressBar1::getSinAlph(){
    return sinAlph;
}

QColor WaterProgressBar1::getWaterColor(){
    return waterColor;
}

float WaterProgressBar1::getValue(){
    return value;
}

void WaterProgressBar1::drawWater(QPainter* painter){
    QRect rect(-radius,-radius,2*radius,2*radius);
    int startX = -radius;
    int startY = -radius;
    int endX = radius;
    int endY = radius;
    float height = radius-((value*radius)/50);

    QPainterPath waterPath1;
    waterPath1.moveTo(startX,endY);
    QPainterPath waterPath2;
    waterPath2.moveTo(startX,endY);

    for(int i = startX;i<=endX;i++){
        float y1,y2;

        y1 = sinA*qSin(sinAlph*i+offset)+height;
        y2 = sinA*qSin(sinAlph*i+30+offset)+height;
        if(value == 0){
            y1 = y2 = endY;
        }
        if(value == 100){
            y1 = y2 = 0;
        }
        waterPath1.lineTo(i,y1);
        waterPath2.lineTo(i,y2);
    }
    waterPath1.lineTo(endX,endY);
    waterPath2.lineTo(endX,endY);

    QPainterPath bigPath;
    bigPath.addEllipse(rect);
    waterPath1 = bigPath.intersected(waterPath1);
    waterPath2 = bigPath.intersected(waterPath2);
    painter->save();
    painter->setPen(Qt::NoPen);
    waterColor.setAlpha(180);
    painter->setBrush(waterColor);
    painter->drawPath(waterPath2);
    waterColor.setAlpha(100);
    painter->setBrush(waterColor);
    painter->drawPath(waterPath1);


    painter->restore();
}

void WaterProgressBar1::drawText(QPainter* painter){
    painter->save();
    QString text = QString("%1%").arg(value);
    QFont font = painter->font();
    font.setPixelSize(40);
    painter->setFont(font);
    QPen pen = painter->pen();
    pen.setColor(Qt::white);
    pen.setWidth(4);
    painter->setPen(pen);
    QRect rect(-radius,-radius,radius*2,radius*2);
    painter->drawText(rect,Qt::AlignCenter,text);
    painter->restore();
}

void WaterProgressBar1::drawBg(QPainter* painter){
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(QColor(bgColor));
    QRect rect(-outRadius,-outRadius,outRadius*2,outRadius*2);
    painter->drawEllipse(rect);
    painter->restore();
}

 void WaterProgressBar1::drawE(QPainter* painter){
     painter->save();

     QPainterPath path;
     QPainterPath subpath;

     QRect out(-outERadius,-outERadius,2*outERadius,2*outERadius);
     QRect inn(-innERadius,-innERadius,2*innERadius,2*innERadius);
     float range = (value*1.0/100)*360;

     path.arcTo(out,-range,range);
     subpath.addEllipse(inn);
     path -= subpath;
     painter->setPen(Qt::NoPen);
     painter->setBrush(waterColor);

     painter->drawPath(path);

     painter->restore();
 }
waterprogressbar2.cpp
#include "waterprogressbar2.h"
#include "ui_waterprogressbar2.h"
#include<QPainter>
#include<QTimer>
#include<QDebug>
#include<qmath.h>

WaterProgressBar2::WaterProgressBar2(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::WaterProgressBar2)
{
    ui->setupUi(this);
    QTimer *timer = new QTimer;
    connect(timer,QTimer::timeout,this,[=](){
        this->offset += 0.6;
        update();
    });
    timer->start(100);
}

WaterProgressBar2::~WaterProgressBar2()
{
    delete ui;
}

void WaterProgressBar2::paintEvent(QPaintEvent *event){
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);

    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);


    drawBg(&painter);
    drawWater(&painter);
    drawText(&painter);

}

void WaterProgressBar2::updateValue(float va){
    this->value = va;
    update();
}

void WaterProgressBar2::setSinA(float sinA){
    this->sinA = sinA;
    update();
}

void WaterProgressBar2::setSinAlph(float alph){
    this->sinAlph = alph;
    update();
}

void WaterProgressBar2::setOffset(float set){
    this->offset = set;
    update();
}

void WaterProgressBar2::setWaterColor(QColor color){
    waterColor = color;
    update();
}

float WaterProgressBar2::getSinA(){
    return sinA;
}

float WaterProgressBar2::getSinAlph(){
    return sinAlph;
}

QColor WaterProgressBar2::getWaterColor(){
    return waterColor;
}

float WaterProgressBar2::getValue(){
    return value;
}

void WaterProgressBar2::drawWater(QPainter* painter){
    QRect rect(-radius,-radius,2*radius,2*radius);
    int startX = -radius;
    int startY = -radius;
    int endX = radius;
    int endY = radius;
    float height = radius-((value*radius)/50);

    QPainterPath waterPath1;
    waterPath1.moveTo(startX,endY);
    QPainterPath waterPath2;
    waterPath2.moveTo(startX,endY);

    for(int i = startX;i<=endX;i++){
        float y1,y2;

        y1 = sinA*qSin(sinAlph*i+offset)+height;
        y2 = sinA*qSin(sinAlph*i+30+offset)+height;
        if(value == 0){
            y1 = y2 = endY;
        }
        if(value == 100){
            y1 = y2 = 0;
        }
        waterPath1.lineTo(i,y1);
        waterPath2.lineTo(i,y2);
    }
    waterPath1.lineTo(endX,endY);
    waterPath2.lineTo(endX,endY);

    QPainterPath bigPath;
    bigPath.addEllipse(rect);
    waterPath1 = bigPath.intersected(waterPath1);
    waterPath2 = bigPath.intersected(waterPath2);
    painter->save();
    painter->setPen(Qt::NoPen);
    waterColor.setAlpha(180);
    painter->setBrush(waterColor);
    painter->drawPath(waterPath2);
    waterColor.setAlpha(100);
    painter->setBrush(waterColor);
    painter->drawPath(waterPath1);


    painter->restore();
}

void WaterProgressBar2::drawText(QPainter* painter){
    painter->save();
    QString text = QString("%1%").arg(value);
    QFont font = painter->font();
    font.setPixelSize(40);
    painter->setFont(font);
    QPen pen = painter->pen();
    pen.setColor(Qt::white);
    pen.setWidth(4);
    painter->setPen(pen);
    QRect rect(-radius,-radius,radius*2,radius*2);
    painter->drawText(rect,Qt::AlignCenter,text);
    painter->restore();
}

void WaterProgressBar2::drawBg(QPainter* painter){
    painter->save();
    painter->setBrush(QColor(bgColor));
    QRect rect(-radius,-radius,radius*2,radius*2);
    painter->drawEllipse(rect);
    painter->restore();
}
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QColorDialog>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->pushButton->setAutoFillBackground(true);

    ui->horizontalSlider_3->setValue(ui->widget->getValue());
    ui->horizontalSlider->setValue(ui->widget->getSinA());
    ui->horizontalSlider_2->setValue(ui->widget->getSinAlph());
    ui->pushButton->setPalette(QPalette(ui->widget->getWaterColor()));

}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    QColorDialog *dlg = new QColorDialog(this);
    QColor color = dlg->getColor();
    ui->widget->setWaterColor(color);
    ui->widget_2->setWaterColor(color);
    ui->pushButton->setPalette(QPalette(color));
}


void Widget::on_horizontalSlider_3_sliderMoved(int position)
{
    ui->widget->updateValue(position);
    ui->widget_2->updateValue(position);
}

void Widget::on_horizontalSlider_sliderMoved(int position)
{
    //浪高
    ui->widget->setSinA(position*1.0/10);
    ui->widget_2->setSinA(position*1.0/10);
}

void Widget::on_horizontalSlider_2_sliderMoved(int position)
{
    //频率
    ui->widget->setSinAlph(position*0.001);
    ui->widget_2->setSinAlph(position*0.001);
}

以上,自绘控件还是很有意思的,以后可以多加学习。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现渐变颜色的进度条,可以通过继承ProgressBar控件来实现自定义控件。具体步骤如下: 1. 创建一个类,继承自ProgressBar控件。 2. 在该类的构造函数中,调用SetStyle方法,设置控件的UserPaint和AllPaintingInWmPaint属性为True,同时将DoubleBuffered属性设置为True,以提高控件的绘制效率。 3. 重写OnPaint方法,实现渐变颜色的绘制。在该方法中,可以使用LinearGradientBrush或HatchBrush来实现渐变的效果。 4. 重写OnSizeChanged方法,以便在控件大小发生变化时重新绘制控件。 下面是一个简单的示例代码,演示如何实现渐变颜色的进度条控件: ``` csharp using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace CustomControls { public class GradientProgressBar : ProgressBar { public GradientProgressBar() { // 设置控件的绘制样式 SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true); } protected override void OnPaint(PaintEventArgs e) { // 绘制背景色 e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle); // 计算进度条的宽度 int width = (int)(ClientRectangle.Width * ((double)Value / Maximum)) - 1; if (width > 0) { // 计算渐变的颜色 Color startColor = Color.FromArgb(255, 0, 0); Color endColor = Color.FromArgb(0, 255, 0); LinearGradientBrush brush = new LinearGradientBrush(ClientRectangle, startColor, endColor, LinearGradientMode.Horizontal); // 绘制渐变进度条 e.Graphics.FillRectangle(brush, ClientRectangle.X, ClientRectangle.Y, width, ClientRectangle.Height); } } protected override void OnSizeChanged(System.EventArgs e) { base.OnSizeChanged(e); Invalidate(); } } } ``` 使用该控件时,只需要在窗体上添加一个GradientProgressBar控件即可。你可以自定义控件的样式,包括颜色、渐变方向等,以满足你的需要。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值