zoukankan      html  css  js  c++  java
  • 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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

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

  • 相关阅读:
    DDL-表的管理
    DDL-库的管理
    Linux虚拟机--进入MySQL报错的解决办法
    前端底层-原型
    前端底层-对象与构造函数
    前端底层-this
    前端底层-DOM
    前端底层-数据类型与数据的三大存储格式
    前端底层-函数
    前端底层-数据类型与全局属性
  • 原文地址:https://www.cnblogs.com/FKdelphi/p/14654093.html
Copyright © 2011-2022 走看看