直接上图,如图所示,在写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);
}
以上,自绘控件还是很有意思的,以后可以多加学习。