用法:
QWidget的话:setGeometry()
Item的话:setPos()
一般大家用的都是 QWidget,所以这里只对 setGeometry() 解释一下
官方文档对 setGeometry() 的解释是:
用法其实很简单:
- x、y 是控件的横纵坐标
- w、h 是控件的宽和高
#ifndef WATERPROGRESSBAR_H
#define WATERPROGRESSBAR_H
#include <QWidget>
class WaterProgressBar : public QWidget//继承QWidget
{
Q_OBJECT
public:
explicit WaterProgressBar(QWidget *parent = nullptr);
void setVaule(int value);
public slots:
void updaterWater();//定时更新,让波浪动起来
protected:
void paintEvent(QPaintEvent *event) override;//自绘控件
//实现左右拖动改变value
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
int m_value;
qreal m_offset;
bool m_isPressed;
QPoint m_startPoint;
void drawWater(QPainter* painter);//画水波浪
void drawText(QPainter* painter);//画中间数值
void drawBg(QPainter* painter);//画背景
};
#endif // WATERPROGRESSBAR_H
#include "WaterProgressBar.h"
#include <QPainter>
#include <QtMath>
#include <QTimer>
#include <QMouseEvent>
WaterProgressBar::WaterProgressBar(QWidget *parent) : QWidget(parent)
{
m_value = 0;
m_offset = 0;
m_isPressed = false;
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &WaterProgressBar::updaterWater);
timer->start(30);//定时30毫秒
}
void WaterProgressBar::setVaule(int value)
{
m_value = value;
update();
}
void WaterProgressBar::updaterWater()
{
m_offset=m_offset+0.15;//波浪偏移
if (m_offset >= 360)
m_offset = 0;
update();
}
void WaterProgressBar::paintEvent(QPaintEvent *event)
{
Q_UNUSED(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);//设置坐标系拉伸为200*200
drawBg(&painter);//画背景
drawWater(&painter);//画水波浪
drawText(&painter);//画中间数值
}
void WaterProgressBar::drawWater(QPainter* painter)
{
int radius = 100;//坐标系高度,上为-,下为+
if (m_value == 0){//没波浪,不用画
return;
}
else if (m_value == 100) {//波浪满,直接画圆
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(100, 180, 250, 230)));
painter->drawEllipse(QRect(-radius, -radius, radius*2, radius*2));
painter->restore();
}
else//画波浪
{
int height = 2*(-m_value+50);//波浪在坐标系中的高度位置
painter->save();
QPainterPath wavePath; //波浪区域
QPainterPath wavePath2; //波浪区域
wavePath.moveTo(-radius, radius);//第一点坐标为(0,height);
for(int x = -radius; x < radius; x++) //x从0~w的值而改变,从而得到正弦曲线
{
double waveY = 4*qSin(1.8*(x*M_PI/180 + m_offset)) + height;// waveY随着x的值改变而改变,从而得到正弦曲线
wavePath.lineTo(x, waveY); //从上一个绘制点画一条线到(x,waveY);
}
wavePath.lineTo(radius, radius); //右下角,坐标(width, height),移动到右下角结束点,整体形成一个闭合路径
wavePath2.moveTo(-radius, radius);//第一点坐标为(0,height);
for(int x = -radius; x < radius; x++) //x从0~w的值而改变,从而得到正弦曲线
{
double waveY = 4*qSin(1.8*(x*M_PI/180 + m_offset + 2)) + height;// waveY随着x的值改变而改变,从而得到正弦曲线
wavePath2.lineTo(x, waveY); //从上一个绘制点画一条线到(x,waveY);
}
wavePath2.lineTo(radius, radius); //右下角,坐标(width, height),移动到右下角结束点,整体形成一个闭合路径
QPainterPath bigPath;
bigPath.addEllipse(QRect(-radius, -radius, radius*2, radius*2));
wavePath = bigPath.intersected(wavePath);
wavePath2 = bigPath.intersected(wavePath2);
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(100, 184, 255, 80)));
painter->drawPath(wavePath); //绘制路径
painter->setBrush(QBrush(QColor(100, 180, 250, 230)));
painter->drawPath(wavePath2); //绘制路径
painter->restore();
}
}
void WaterProgressBar::drawText(QPainter* painter){
int radius = 40;
painter->save();
QString text = QString("%1%").arg(m_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 WaterProgressBar::drawBg(QPainter* painter){
int outRadius = 100;
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(40,40,40));
QRect rect(-outRadius,-outRadius,outRadius*2,outRadius*2);
painter->drawEllipse(rect);
painter->restore();
}
void WaterProgressBar::mousePressEvent(QMouseEvent *event)
{
m_isPressed = true;
m_startPoint = event->pos();
}
void WaterProgressBar::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event)
m_isPressed = false;
}
void WaterProgressBar::mouseMoveEvent(QMouseEvent *event)
{
if (m_isPressed)
{
if (m_startPoint.x()<=0 || m_startPoint.x()>=width())
{
m_startPoint = event->pos();
return;
}
if (event->pos().x() > m_startPoint.x())
{
int addVaule = qCeil((100-m_value)*1.0/(width()-m_startPoint.x()));
if (m_value < 100)
setVaule(m_value+addVaule);
}
else if (event->pos().x() < m_startPoint.x()){
int addVaule = qCeil(m_value*1.0/m_startPoint.x());
if (m_value > 0)
setVaule(m_value-addVaule);
}
m_startPoint = event->pos();
}
}
#include "widget.h"
#include "ui_widget.h"
#include "waterprogressbar.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
WaterProgressBar *w = new WaterProgressBar(); //创建 WaterProgressBar 对象
w->setGeometry(rect().x()+200, rect().y()+10,
100, 300); //设置大小
w->setParent(this); //设置父窗口
}
Widget::~Widget()
{
delete ui;
}
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}