Qt5利用自绘QPainter实现水波纹进度条QProgressBarWater

.pro

 1 QT       += core gui
 2 
 3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 4 
 5 CONFIG += c++11
 6 
 7 # The following define makes your compiler emit warnings if you use
 8 # any Qt feature that has been marked deprecated (the exact warnings
 9 # depend on your compiler). Please consult the documentation of the
10 # deprecated API in order to know how to port your code away from it.
11 DEFINES += QT_DEPRECATED_WARNINGS
12 
13 # You can also make your code fail to compile if it uses deprecated APIs.
14 # In order to do so, uncomment the following line.
15 # You can also select to disable deprecated APIs only up to a certain version of Qt.
16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
17 
18 SOURCES += 
19     QProgressBarWater.cpp 
20     main.cpp 
21     mainwindow.cpp
22 
23 HEADERS += 
24     QProgressBarWater.h 
25     mainwindow.h
26 
27 FORMS += 
28     mainwindow.ui
29 
30 # Default rules for deployment.
31 qnx: target.path = /tmp/$${TARGET}/bin
32 else: unix:!android: target.path = /opt/$${TARGET}/bin
33 !isEmpty(target.path): INSTALLS += target
View Code

main.cpp

 1 #include "mainwindow.h"
 2 
 3 #include <QApplication>
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     QApplication a(argc, argv);
 8     MainWindow w;
 9     w.show();
10     return a.exec();
11 }
View Code

mainwindow.h

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 
 6 #include "QProgressBarWater.h"
 7 
 8 QT_BEGIN_NAMESPACE
 9 namespace Ui { class MainWindow; }
10 QT_END_NAMESPACE
11 
12 class MainWindow : public QMainWindow
13 {
14     Q_OBJECT
15 
16 public:
17     MainWindow(QWidget *parent = nullptr);
18     ~MainWindow();
19 
20 private slots:
21     void on_horizontalSlider_valueChanged(int value);
22 
23 private:
24     Ui::MainWindow *ui;
25     QProgressBarWater *m_pQProgressBarWater;
26 };
27 #endif // MAINWINDOW_H
View Code

mainwindow.cpp

 1 #include "mainwindow.h"
 2 #include "ui_mainwindow.h"
 3 
 4 MainWindow::MainWindow(QWidget *parent)
 5     : QMainWindow(parent)
 6     , ui(new Ui::MainWindow)
 7 {
 8     ui->setupUi(this);
 9 
10     m_pQProgressBarWater = new QProgressBarWater(this);
11     m_pQProgressBarWater->setGeometry(20, 20, 200, 300);
12     m_pQProgressBarWater->setMaxValue(100);
13     m_pQProgressBarWater->setMinValue(0);
14 }
15 
16 MainWindow::~MainWindow()
17 {
18     delete ui;
19 }
20 
21 void MainWindow::on_horizontalSlider_valueChanged(int value)
22 {
23     m_pQProgressBarWater->setValue(value);
24 }
View Code

mainwindow.ui

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <ui version="4.0">
 3  <class>MainWindow</class>
 4  <widget class="QMainWindow" name="MainWindow">
 5   <property name="geometry">
 6    <rect>
 7     <x>0</x>
 8     <y>0</y>
 9     <width>401</width>
10     <height>345</height>
11    </rect>
12   </property>
13   <property name="windowTitle">
14    <string>MainWindow</string>
15   </property>
16   <widget class="QWidget" name="centralwidget">
17    <widget class="QSlider" name="horizontalSlider">
18     <property name="geometry">
19      <rect>
20       <x>20</x>
21       <y>250</y>
22       <width>351</width>
23       <height>22</height>
24      </rect>
25     </property>
26     <property name="maximum">
27      <number>100</number>
28     </property>
29     <property name="orientation">
30      <enum>Qt::Horizontal</enum>
31     </property>
32    </widget>
33   </widget>
34   <widget class="QMenuBar" name="menubar">
35    <property name="geometry">
36     <rect>
37      <x>0</x>
38      <y>0</y>
39      <width>401</width>
40      <height>23</height>
41     </rect>
42    </property>
43   </widget>
44   <widget class="QStatusBar" name="statusbar"/>
45  </widget>
46  <resources/>
47  <connections/>
48 </ui>
View Code
QProgressBarWater.h
 1 // https://blog.csdn.net/u012156872/article/details/110396056
 2 #ifndef QPROGRESSBARWATER_H
 3 #define QPROGRESSBARWATER_H
 4 
 5 
 6 #include <QWidget>
 7 #include <QPainter>
 8 #include <QPaintEvent>
 9 
10 class QProgressBarWater : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit QProgressBarWater(QWidget *parent = nullptr);
16 
17     enum PercentStyle_Type{
18         PercentStyle_Rect = 0,  //矩形
19         PercentStyle_Circle,    //
20         PercentStyle_Ellipse,   //椭圆
21     };
22 
23 signals:
24 
25 public slots:
26 
27 protected:
28     virtual void paintEvent(QPaintEvent *event);
29     virtual void timerEvent(QTimerEvent *event);
30 
31 private:
32     PercentStyle_Type m_percentStyle = PercentStyle_Circle;
33     QColor m_frontColor = Qt::green;
34     QColor m_textColor = Qt::white;
35     QColor m_boderColor = Qt::white;
36     QColor m_bgColor = QColor(0, 200, 0, 200);
37     QFont m_font;
38     int m_value = 50;
39     int m_minValue = 0;
40     int m_maxValue = 100;
41     int m_waterDensity = 1;
42     double m_waterHeight = 0.03;
43     double m_offset = 50;
44     int m_borderWidth = 0;
45 
46 
47     void drawValue(QPainter *painter);
48 
49 public:
50     void setValue(int value);
51     int value();
52     void setMaxValue(int value);
53     int maxValue();
54     void setMinValue(int value);
55     int minValue();
56     void setPercentStyle(QProgressBarWater::PercentStyle_Type type);
57     PercentStyle_Type percentStyle();
58     void setWaterDensity(int val);
59     int waterDensity();
60     void setColor(QColor col);
61     QColor color();
62     void setWaterHeight(double val);
63     double waterHeight();
64     void setBorderWidth(int val);
65     int borderWidth();
66     void setTextColor(QColor col);
67     QColor textColor();
68     void setBoderColor(QColor col);
69     QColor boderColor();
70     void setBgColor(QColor col);
71     QColor bgColor();
72 };
73 
74 #endif // QPROGRESSBARWATER_H
View Code
QProgressBarWater.cpp
  1 #include "QProgressBarWater.h"
  2 
  3 
  4 #include <QPainter>
  5 #include <qmath.h>
  6 #include <QBrush>
  7 #include <QColor>
  8 #include <QLinearGradient>
  9 
 10 QProgressBarWater::QProgressBarWater(QWidget *parent) : QWidget(parent)
 11 {
 12     m_font.setFamily("Microsoft YaHei");
 13     this->startTimer(80);
 14 }
 15 
 16 void QProgressBarWater::setValue(int value)
 17 {
 18     m_value = qMax(m_minValue, qMin(m_maxValue, value));
 19 }
 20 
 21 int QProgressBarWater::value()
 22 {
 23     return m_value;
 24 }
 25 
 26 void QProgressBarWater::setMaxValue(int value)
 27 {
 28     m_maxValue = value;
 29 }
 30 
 31 int QProgressBarWater::maxValue()
 32 {
 33     return m_maxValue;
 34 }
 35 
 36 void QProgressBarWater::setMinValue(int value)
 37 {
 38     m_minValue = value;
 39 }
 40 
 41 int QProgressBarWater::minValue()
 42 {
 43     return m_minValue;
 44 }
 45 
 46 void QProgressBarWater::setPercentStyle(QProgressBarWater::PercentStyle_Type type)
 47 {
 48     m_percentStyle = type;
 49 }
 50 
 51 QProgressBarWater::PercentStyle_Type QProgressBarWater::percentStyle()
 52 {
 53     return m_percentStyle;
 54 }
 55 
 56 void QProgressBarWater::setWaterDensity(int val)
 57 {
 58     m_waterDensity = val;
 59 }
 60 
 61 int QProgressBarWater::waterDensity()
 62 {
 63     return m_waterDensity;
 64 }
 65 
 66 void QProgressBarWater::setColor(QColor col)
 67 {
 68     m_frontColor = col;
 69 }
 70 
 71 QColor QProgressBarWater::color()
 72 {
 73     return m_frontColor;
 74 }
 75 
 76 void QProgressBarWater::setWaterHeight(double val)
 77 {
 78     m_waterHeight = val;
 79 }
 80 
 81 double QProgressBarWater::waterHeight()
 82 {
 83     return m_waterHeight;
 84 }
 85 
 86 void QProgressBarWater::setBorderWidth(int val)
 87 {
 88     m_borderWidth = val;
 89 }
 90 
 91 int QProgressBarWater::borderWidth()
 92 {
 93     return m_borderWidth;
 94 }
 95 
 96 void QProgressBarWater::setTextColor(QColor col)
 97 {
 98     m_textColor = col;
 99 }
100 
101 QColor QProgressBarWater::textColor()
102 {
103     return m_textColor;
104 }
105 
106 void QProgressBarWater::setBoderColor(QColor col)
107 {
108     m_boderColor = col;
109 }
110 
111 QColor QProgressBarWater::boderColor()
112 {
113     return m_boderColor;
114 }
115 
116 void QProgressBarWater::setBgColor(QColor col)
117 {
118     m_bgColor = col;
119 }
120 
121 QColor QProgressBarWater::bgColor()
122 {
123     return m_bgColor;
124 }
125 
126 void QProgressBarWater::timerEvent(QTimerEvent *event)
127 {
128     Q_UNUSED(event);
129 
130     this->update();
131 }
132 
133 void QProgressBarWater::drawValue(QPainter *painter)
134 {
135     Q_UNUSED(painter);
136     painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform); // 反锯齿;
137 
138     int height = this->height();
139     int width = this->width();
140     int side = qMin(width, height);
141 
142     //计算当前值所占百分比
143     double percent = 1 - (double)(m_value - m_minValue) / (m_maxValue - m_minValue);
144 
145     //正弦曲线公式 y = A * sin(ωx + φ) + k
146     //w表示周期,可以理解为水波的密度,值越大密度越大(浪越密集 ^_^),取值 密度*M_PI/宽度
147     double w = 0.038;//m_waterDensity * M_PI * 1.6/ width;
148 
149     //A表示振幅,可以理解为水波的高度,值越大高度越高(越浪 ^_^),取值高度的百分比
150     double A = height * m_waterHeight;
151 
152     //k表示y轴偏移,可以理解为进度,取值高度的进度百分比
153     double k = height * percent;
154 
155     //第一条波浪路径集合
156     QPainterPath waterPath1;
157 
158     //第二条波浪路径集合
159     QPainterPath waterPath2;
160 
161     //移动到左上角起始点
162     waterPath1.moveTo(0, height);
163     waterPath2.moveTo(0, height);
164 
165     m_offset += 0.6;
166     if (m_offset > (width / 2)) {
167         m_offset = 0;
168     }
169 
170     double waterY1 = 0.0;
171     double waterY2 = 0.0;
172     for(int x = 0; x <= width; x++) {
173         //第一条波浪Y轴
174         waterY1 = (double)(A * qSin(w * x + m_offset)) + k;
175 
176         //第二条波浪Y轴
177         waterY2 = (double)(A * qSin(w * x + m_offset + (width / 2 * w))) + k;
178 
179         //如果当前值为最小值则Y轴为高度
180         if (m_value == m_minValue) {
181             waterY1 = height;
182             waterY2 = height;
183         }
184 
185         //如果当前值为最大值则Y轴为0
186         if (m_value == m_maxValue) {
187             waterY1 = 0;
188             waterY2 = 0;
189         }
190 
191         waterPath1.lineTo(x, waterY1);
192         waterPath2.lineTo(x, waterY2);
193     }
194 
195     //移动到右下角结束点,整体形成一个闭合路径
196     waterPath1.lineTo(width, height);
197     waterPath2.lineTo(width, height);
198 
199     //画背景,此处由单一色调改为了渐变色
200     QRadialGradient radialGradient(side / 2, height / 2, side / 2, side / 2, side / 2);
201     radialGradient.setColorAt(0, QColor(0, 0, 255, 100));
202     radialGradient.setColorAt(1.0, QColor(50, 50, 255, 200));
203 
204     QPainterPath bigPath;
205     if (m_percentStyle == PercentStyle_Rect) {
206         width = width - m_borderWidth * 2;
207         height = height - m_borderWidth * 2;
208         bigPath.addRect(m_borderWidth, m_borderWidth, width, height);
209         //painter->setBrush(m_boderColor);
210         painter->setBrush(QBrush(radialGradient));
211         painter->drawRect(this->rect());
212         //painter->setBrush(m_bgColor);
213         painter->setBrush(QBrush(radialGradient));
214         painter->drawRect(m_borderWidth, m_borderWidth, width, height);
215     }
216     else if (m_percentStyle == PercentStyle_Circle) {
217         //painter->setBrush(m_boderColor);
218 //        painter->setBrush(QBrush(radialGradient));
219 //        painter->drawEllipse((width - side) / 2, (height - side) / 2, side, height);
220         side = side - m_borderWidth * 2;
221         bigPath.addEllipse((width - side) / 2, m_borderWidth, side, side);
222         //painter->setBrush(m_bgColor);
223         painter->setBrush(QBrush(radialGradient));
224         painter->setPen(m_bgColor);
225         painter->drawEllipse((width - side) / 2, m_borderWidth, side, side);
226     }
227     else if (m_percentStyle == PercentStyle_Ellipse) {
228         width = width - m_borderWidth * 2;
229         height = height - m_borderWidth * 2;
230         bigPath.addEllipse(m_borderWidth, m_borderWidth, width, height);
231         //painter->setBrush(m_boderColor);
232         painter->setBrush(QBrush(radialGradient));
233         painter->drawEllipse(this->rect());
234         //painter->setBrush(m_bgColor);
235         painter->setBrush(QBrush(radialGradient));
236         painter->drawEllipse(m_borderWidth, m_borderWidth, width, height);
237     }
238 
239     painter->save();
240 
241     //新路径,用大路径减去波浪区域的路径,形成遮罩效果
242     QPainterPath path;
243     painter->setPen(Qt::NoPen);
244     QColor waterColor1 = m_frontColor;
245     waterColor1.setAlpha(100);
246     QColor waterColor2 = m_frontColor;
247     waterColor2.setAlpha(180);
248 
249     QLinearGradient linearGradient1(0,0,0,side);
250     linearGradient1.setColorAt(0.2,QColor(0, 255, 255, 100));
251     linearGradient1.setColorAt(0.6,QColor(50, 200, 50, 100));
252     linearGradient1.setColorAt(1.0,QColor(25, 150, 25, 100));
253 
254     QLinearGradient linearGradient2(0,0,0,side);
255     linearGradient2.setColorAt(0.2,QColor(0, 255, 255, 180));
256     linearGradient2.setColorAt(0.6,QColor(50, 200, 50, 180));
257     linearGradient2.setColorAt(1.0,QColor(25, 150, 25, 180));
258 
259     //第一条波浪挖去后的路径
260     path = bigPath.intersected(waterPath1);
261     painter->setBrush(QBrush(linearGradient1));
262     painter->drawPath(path);
263 
264     //第二条波浪挖去后的路径
265     path = bigPath.intersected(waterPath2);
266     painter->setBrush(QBrush(linearGradient2));
267     painter->drawPath(path);
268     painter->restore();
269 
270     //绘制文字
271     m_font.setPixelSize(this->width()/4);
272     painter->setPen(m_textColor);
273     painter->setFont(m_font);
274     painter->drawText(this->rect(), Qt::AlignCenter, QString("%0%").arg(QString::number(m_value)));
275 }
276 
277 void QProgressBarWater::paintEvent(QPaintEvent *event)
278 {
279     Q_UNUSED(event);
280 
281     QPainter painter(this);
282     drawValue(&painter);
283 }
View Code
作者:疯狂Delphi
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

欢迎关注我,一起进步!扫描下方二维码即可加我

原文地址:https://www.cnblogs.com/FKdelphi/p/14654093.html