Qt水波进度条Demo

https://blog.csdn.net/u014597198/article/details/78261275?locationNum=7&fps=1

多谢飞扬青春的博客,看到水波形进度条的效果觉得非常不错,于是自己也模仿着做了一个类似的,效果图:

原理:

利用正弦曲线产生平滑曲线点集合,然后用大路径减去当前进度路径,形成水波效果。 

源码如下:

 
  1. #ifndef SPROGRESSBAR_H

  2. #define SPROGRESSBAR_H

    扫描二维码关注公众号,回复: 2931191 查看本文章
  3.  
  4. #include <QWidget>

  5. #include <QPainter>

  6. #include <QtMath>

  7.  
  8. class SProgressBar : public QWidget

  9. {

  10. Q_OBJECT

  11. public:

  12. explicit SProgressBar(QWidget *parent = 0);

  13.  
  14. enum PercentStyle_Type{

  15. PercentStyle_Rect = 0,//矩形

  16. PercentStyle_Circle,//圆

  17. PercentStyle_Ellipse,//椭圆

  18. };

  19.  
  20. void setValue(int value) {m_value = value;}

  21. int value() {return m_value;}

  22.  
  23. void setMaxValue(int value) {m_maxValue = value;}

  24. int maxValue() {return m_maxValue;}

  25.  
  26. void setMinValue(int value) {m_minValue = value;}

  27. int minValue() {return m_minValue;}

  28.  
  29. void setPercentStyle(SProgressBar::PercentStyle_Type type) {m_percentStyle = type;}

  30. PercentStyle_Type percentStyle() {return m_percentStyle;}

  31.  
  32. void setWaterDensity(int val) {m_waterDensity = val;}

  33. int waterDensity() {return m_waterDensity;}

  34.  
  35. void setColor(QColor col) {m_usedColor = col;}

  36. QColor color() {return m_usedColor;}

  37.  
  38. void setWaterHeight(double val) {m_waterHeight = val;}

  39. double waterHeight() {return m_waterHeight;}

  40.  
  41. void setBorderWidth(int val) {m_borderWidth = val;}

  42. int borderWidth() {return m_borderWidth;}

  43.  
  44. void setTextColor(QColor col) {m_textColor = col;}

  45. QColor textColor() {return m_textColor;}

  46.  
  47. void setBoderColor(QColor col) {m_boderColor = col;}

  48. QColor boderColor() {return m_boderColor;}

  49.  
  50. void setBgColor(QColor col) {m_bgColor = col;}

  51. QColor bgColor() {return m_bgColor;}

  52. protected:

  53. void paintEvent(QPaintEvent *event);

  54. void timerEvent(QTimerEvent *event);

  55. private:

  56. PercentStyle_Type m_percentStyle = PercentStyle_Rect;

  57. QColor m_usedColor = QColor(180,255,255);

  58. QColor m_textColor = Qt::white;

  59. QColor m_boderColor = Qt::black;

  60. QColor m_bgColor = Qt::gray;

  61. QFont m_font;

  62. int m_value = 80;

  63. int m_minValue = 0;

  64. int m_maxValue = 100;

  65. int m_waterDensity = 10; // 水波的密度

  66. double m_waterHeight = 0.03;

  67. double m_offset = 50;

  68. int m_borderWidth = 10;

  69. };

  70.  
  71. #endif // SPROGRESSBAR_H

  72.  
 
  1. #include "sprogressbar.h"

  2.  
  3. SProgressBar::SProgressBar(QWidget *parent) : QWidget(parent)

  4. {

  5. m_font.setFamily("Microsoft YaHei");

  6. this->startTimer(80);

  7. }

  8.  
  9. void SProgressBar::paintEvent(QPaintEvent *event)

  10. {

  11. Q_UNUSED(event);

  12. QPainter painter(this);

  13. painter.setRenderHint(QPainter::Antialiasing); // 反锯齿;

  14. int height = this->height();

  15. int width = this->width();

  16. int side = qMin(width, height);

  17.  
  18. //计算当前值所占百分比

  19. double percent = 1 - (double)(m_value - m_minValue) / (m_maxValue - m_minValue);

  20.  
  21. //正弦曲线公式 y = A * sin(ωx + φ) + k

  22. //w表示周期,可以理解为水波的密度,值越大密度越大(浪越密集 ^_^),取值 密度*M_PI/宽度

  23. double w = m_waterDensity * M_PI / width;

  24. //A表示振幅,可以理解为水波的高度,值越大高度越高(越浪 ^_^),取值高度的百分比

  25. double A = height * m_waterHeight;

  26. //k表示y轴偏移,可以理解为进度,取值高度的进度百分比

  27. double k = height * percent;

  28.  
  29. //第一条波浪路径集合

  30. QPainterPath waterPath1;

  31. //第二条波浪路径集合

  32. QPainterPath waterPath2;

  33.  
  34. //移动到左上角起始点

  35. waterPath1.moveTo(0, height);

  36. waterPath2.moveTo(0, height);

  37.  
  38. m_offset += 0.6;

  39. if (m_offset > (width / 2)) {

  40. m_offset = 0;

  41. }

  42.  
  43. for(int x = 0; x <= width; x++) {

  44. //第一条波浪Y轴

  45. double waterY1 = (double)(A * sin(w * x + m_offset)) + k;

  46.  
  47. //第二条波浪Y轴

  48. double waterY2 = (double)(A * sin(w * x + m_offset + (width / 2 * w))) + k;

  49.  
  50. //如果当前值为最小值则Y轴为高度

  51. if (m_value == m_minValue) {

  52. waterY1 = height;

  53. waterY2 = height;

  54. }

  55.  
  56. //如果当前值为最大值则Y轴为0

  57. if (m_value == m_maxValue) {

  58. waterY1 = 0;

  59. waterY2 = 0;

  60. }

  61.  
  62. waterPath1.lineTo(x, waterY1);

  63. waterPath2.lineTo(x, waterY2);

  64. }

  65.  
  66. //移动到右下角结束点,整体形成一个闭合路径

  67. waterPath1.lineTo(width, height);

  68. waterPath2.lineTo(width, height);

  69.  
  70. //大路径

  71. QPainterPath bigPath;

  72. if (m_percentStyle == PercentStyle_Rect) {

  73. width = width - m_borderWidth * 2;

  74. height = height - m_borderWidth * 2;

  75. bigPath.addRect(m_borderWidth, m_borderWidth, width, height);

  76. painter.setBrush(m_boderColor);

  77. painter.drawRect(this->rect());

  78. painter.setBrush(m_bgColor);

  79. painter.drawRect(m_borderWidth, m_borderWidth, width, height);

  80. } else if (m_percentStyle == PercentStyle_Circle) {

  81. painter.setBrush(m_boderColor);

  82. painter.drawEllipse((width - side) / 2, (height - side) / 2, side, height);

  83. side = side - m_borderWidth * 2;

  84. bigPath.addEllipse((width - side) / 2, m_borderWidth, side, side);

  85. painter.setBrush(m_bgColor);

  86. painter.drawEllipse((width - side) / 2, m_borderWidth, side, side);

  87. } else if (m_percentStyle == PercentStyle_Ellipse) {

  88. width = width - m_borderWidth * 2;

  89. height = height - m_borderWidth * 2;

  90. bigPath.addEllipse(m_borderWidth, m_borderWidth, width, height);

  91. painter.setBrush(m_boderColor);

  92. painter.drawEllipse(this->rect());

  93. painter.setBrush(m_bgColor);

  94. painter.drawEllipse(m_borderWidth, m_borderWidth, width, height);

  95. }

  96.  
  97. painter.save();

  98.  
  99. //新路径,用大路径减去波浪区域的路径,形成遮罩效果

  100. QPainterPath path;

  101. painter.setPen(Qt::NoPen);

  102. QColor waterColor1 = m_usedColor;

  103. waterColor1.setAlpha(100);

  104. QColor waterColor2 = m_usedColor;

  105. waterColor2.setAlpha(180);

  106.  
  107. //第一条波浪挖去后的路径

  108. path = bigPath.intersected(waterPath1);

  109. painter.setBrush(waterColor1);

  110. painter.drawPath(path);

  111.  
  112. //第二条波浪挖去后的路径

  113. path = bigPath.intersected(waterPath2);

  114. painter.setBrush(waterColor2);

  115. painter.drawPath(path);

  116.  
  117. painter.restore();

  118.  
  119. //绘制文字

  120. m_font.setPixelSize(this->width()/4);

  121. painter.setPen(m_textColor);

  122. painter.setFont(m_font);

  123. painter.drawText(this->rect(), Qt::AlignCenter, QString("%0%").arg(QString::number(m_value)));

  124. }

  125.  
  126. void SProgressBar::timerEvent(QTimerEvent *event)

  127. {

  128. Q_UNUSED(event);

  129. this->update();

  130. }

  131.  
 
  1. #ifndef WIDGET_H

  2. #define WIDGET_H

  3.  
  4. #include <QWidget>

  5. #include <QPainter>

  6. #include <QLabel>

  7. #include <QSlider>

  8. #include <QComboBox>

  9. #include <QPushButton>

  10. #include "sprogressbar.h"

  11.  
  12. class Widget : public QWidget

  13. {

  14. Q_OBJECT

  15.  
  16. public:

  17. Widget(QWidget *parent = 0);

  18. void initUI();

  19. private slots:

  20. void onValueChanged(int value);

  21. void onPercentStyle(int type);

  22. void onWaterDesity(int value);

  23. void onColorClicked();

  24. void onWaterHeight(int value);

  25. void onBorderWidth(int value);

  26. void onTextColorClicked();

  27. void onBoderColorClicked();

  28. void onBgColorClicked();

  29. private:

  30. SProgressBar *m_progressBar = Q_NULLPTR;

  31. QLabel* m_valueLab = Q_NULLPTR;

  32. QSlider* m_valueSlider = Q_NULLPTR;

  33. QLabel* m_percentStyleLab = Q_NULLPTR;

  34. QComboBox* m_percentStyleComboBox = Q_NULLPTR;

  35. QLabel* m_waterDesityLab = Q_NULLPTR;

  36. QSlider* m_waterDesitySlider = Q_NULLPTR;

  37. QLabel* m_colorLab = Q_NULLPTR;

  38. QPushButton* m_colorBtn = Q_NULLPTR;

  39. QLabel* m_waterHeightLab = Q_NULLPTR;

  40. QSlider* m_waterHeightSlider = Q_NULLPTR;

  41. QLabel* m_borderWidthLab = Q_NULLPTR;

  42. QSlider* m_borderWidthSlider = Q_NULLPTR;

  43. QLabel* m_textColorLab = Q_NULLPTR;

  44. QPushButton* m_textColorBtn = Q_NULLPTR;

  45. QLabel* m_boderColorLab = Q_NULLPTR;

  46. QPushButton* m_boderColorBtn = Q_NULLPTR;

  47. QLabel* m_bgColorLab = Q_NULLPTR;

  48. QPushButton* m_bgColorBtn = Q_NULLPTR;

  49. };

  50.  
  51. #endif // WIDGET_H

  52.  
 
  1. #include "widget.h"

  2. #include <QColorDialog>

  3. #include <QIcon>

  4.  
  5. Widget::Widget(QWidget *parent)

  6. : QWidget(parent)

  7. {

  8. this->setWindowIcon(QIcon(":/Demo_Hello.ico"));

  9. this->setWindowTitle("水波纹Demo");

  10. initUI();

  11. }

  12.  
  13. void Widget::initUI()

  14. {

  15. this->setFixedSize(900,500);

  16. m_progressBar = new SProgressBar(this);

  17. m_progressBar->resize(600,500);

  18. m_progressBar->move(0,0);

  19. m_valueLab = new QLabel(this);

  20. m_valueLab->setAlignment(Qt::AlignCenter);

  21. m_valueLab->resize(100,30);

  22. m_valueLab->move(600,0);

  23. m_valueLab->setText("\350\277\233\345\272\246"); // 进度

  24. m_valueSlider = new QSlider(this);

  25. m_valueSlider->setOrientation(Qt::Horizontal);

  26. m_valueSlider->resize(180,20);

  27. m_valueSlider->move(700,5);

  28. m_valueSlider->setMaximum(m_progressBar->maxValue());

  29. m_valueSlider->setMinimum(m_progressBar->minValue());

  30. m_valueSlider->setValue(m_progressBar->value());

  31. connect(m_valueSlider, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int)));

  32. m_percentStyleLab = new QLabel(this);

  33. m_percentStyleLab->setAlignment(Qt::AlignCenter);

  34. m_percentStyleLab->resize(100,30);

  35. m_percentStyleLab->move(600,40);

  36. m_percentStyleLab->setText("\345\275\242\347\212\266"); // 形状

  37. m_percentStyleComboBox = new QComboBox(this);

  38. m_percentStyleComboBox->resize(180,30);

  39. m_percentStyleComboBox->move(700,40);

  40. m_percentStyleComboBox->addItem("\347\237\251\345\275\242"); // 矩形

  41. m_percentStyleComboBox->addItem("\345\234\206\345\275\242"); // 圆形

  42. m_percentStyleComboBox->addItem("\346\244\255\345\234\206"); // 椭圆

  43. m_percentStyleComboBox->setCurrentIndex(m_progressBar->percentStyle());

  44. connect(m_percentStyleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onPercentStyle(int)));

  45. m_waterDesityLab = new QLabel(this);

  46. m_waterDesityLab->setAlignment(Qt::AlignCenter);

  47. m_waterDesityLab->resize(100,30);

  48. m_waterDesityLab->move(600,80);

  49. m_waterDesityLab->setText("\346\260\264\346\263\242\347\232\204\345\257\206\345\272\246"); // 水波的密度

  50. m_waterDesitySlider = new QSlider(this);

  51. m_waterDesitySlider->setOrientation(Qt::Horizontal);

  52. m_waterDesitySlider->resize(180,20);

  53. m_waterDesitySlider->move(700,85);

  54. m_waterDesitySlider->setMaximum(100);

  55. m_waterDesitySlider->setMinimum(0);

  56. m_waterDesitySlider->setValue(m_progressBar->waterDensity());

  57. connect(m_waterDesitySlider, SIGNAL(valueChanged(int)), this, SLOT(onWaterDesity(int)));

  58. m_colorLab = new QLabel(this);

  59. m_colorLab->setAlignment(Qt::AlignCenter);

  60. m_colorLab->resize(100,30);

  61. m_colorLab->move(600,120);

  62. m_colorLab->setText("\350\203\214\346\231\257\351\242\234\350\211\262"); // 背景颜色

  63. m_colorBtn = new QPushButton(this);

  64. m_colorBtn->resize(180,20);

  65. m_colorBtn->move(700,125);

  66. QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->color().red())

  67. .arg(m_progressBar->color().green()).arg(m_progressBar->color().blue());

  68. m_colorBtn->setStyleSheet(styleCol);

  69. connect(m_colorBtn, SIGNAL(clicked(bool)),this, SLOT(onColorClicked()));

  70. m_waterHeightLab = new QLabel(this);

  71. m_waterHeightLab->setAlignment(Qt::AlignCenter);

  72. m_waterHeightLab->resize(100,30);

  73. m_waterHeightLab->move(600,160);

  74. m_waterHeightLab->setText("\346\260\264\347\232\204\351\253\230\345\272\246"); // 水的高度

  75. m_waterHeightSlider = new QSlider(this);

  76. m_waterHeightSlider->setOrientation(Qt::Horizontal);

  77. m_waterHeightSlider->resize(180,20);

  78. m_waterHeightSlider->move(700,165);

  79. m_waterHeightSlider->setMaximum(100);

  80. m_waterHeightSlider->setMinimum(0);

  81. m_waterHeightSlider->setValue(m_progressBar->waterHeight()*1000);

  82. connect(m_waterHeightSlider, SIGNAL(valueChanged(int)), this, SLOT(onWaterDesity(int)));

  83. m_borderWidthLab = new QLabel(this);

  84. m_borderWidthLab->setAlignment(Qt::AlignCenter);

  85. m_borderWidthLab->resize(100,30);

  86. m_borderWidthLab->move(600,200);

  87. m_borderWidthLab->setText("\350\276\271\346\241\206\345\256\275\345\272\246"); // 边框宽度

  88. m_borderWidthSlider = new QSlider(this);

  89. m_borderWidthSlider->setOrientation(Qt::Horizontal);

  90. m_borderWidthSlider->resize(180,20);

  91. m_borderWidthSlider->move(700,205);

  92. m_borderWidthSlider->setMaximum(20);

  93. m_borderWidthSlider->setMinimum(0);

  94. m_borderWidthSlider->setValue(m_progressBar->borderWidth());

  95. connect(m_borderWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(onBorderWidth(int)));

  96. m_textColorLab = new QLabel(this);

  97. m_textColorLab->setAlignment(Qt::AlignCenter);

  98. m_textColorLab->resize(100,30);

  99. m_textColorLab->move(600,240);

  100. m_textColorLab->setText("\345\255\227\344\275\223\351\242\234\350\211\262"); // 字体颜色

  101. m_textColorBtn = new QPushButton(this);

  102. m_textColorBtn->resize(180,20);

  103. m_textColorBtn->move(700,245);

  104. QString textCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->textColor().red())

  105. .arg(m_progressBar->textColor().green()).arg(m_progressBar->textColor().blue());

  106. m_textColorBtn->setStyleSheet(textCol);

  107. connect(m_textColorBtn, SIGNAL(clicked(bool)),this, SLOT(onTextColorClicked()));

  108. m_boderColorLab = new QLabel(this);

  109. m_boderColorLab->setAlignment(Qt::AlignCenter);

  110. m_boderColorLab->resize(100,30);

  111. m_boderColorLab->move(600,280);

  112. m_boderColorLab->setText("\350\276\271\346\241\206\351\242\234\350\211\262"); // 边框颜色

  113. m_boderColorBtn = new QPushButton(this);

  114. m_boderColorBtn->resize(180,20);

  115. m_boderColorBtn->move(700,285);

  116. QString boderCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->boderColor().red())

  117. .arg(m_progressBar->boderColor().green()).arg(m_progressBar->boderColor().blue());

  118. m_boderColorBtn->setStyleSheet(boderCol);

  119. connect(m_boderColorBtn, SIGNAL(clicked(bool)),this, SLOT(onBoderColorClicked()));

  120. m_bgColorLab = new QLabel(this);

  121. m_bgColorLab->setAlignment(Qt::AlignCenter);

  122. m_bgColorLab->resize(100,30);

  123. m_bgColorLab->move(600,320);

  124. m_bgColorLab->setText("\346\234\252\345\241\253\345\205\205\351\242\234\350\211\262"); // 未填充颜色

  125. m_bgColorBtn = new QPushButton(this);

  126. m_bgColorBtn->resize(180,20);

  127. m_bgColorBtn->move(700,325);

  128. QString bgCol = QString("background-color:rgb(%0,%1,%2)").arg(m_progressBar->bgColor().red())

  129. .arg(m_progressBar->bgColor().green()).arg(m_progressBar->bgColor().blue());

  130. m_bgColorBtn->setStyleSheet(bgCol);

  131. connect(m_bgColorBtn, SIGNAL(clicked(bool)),this, SLOT(onBgColorClicked()));

  132. }

  133.  
  134. void Widget::onValueChanged(int value)

  135. {

  136. m_progressBar->setValue(value);

  137. }

  138.  
  139. void Widget::onPercentStyle(int type)

  140. {

  141. SProgressBar::PercentStyle_Type index = SProgressBar::PercentStyle_Type(type);

  142. m_progressBar->setPercentStyle(index);

  143. }

  144.  
  145. void Widget::onWaterDesity(int value)

  146. {

  147. m_progressBar->setWaterDensity(value);

  148. }

  149.  
  150. void Widget::onColorClicked()

  151. {

  152. QColor c = QColorDialog::getColor(m_progressBar->color());

  153. if(c.isValid()) {

  154. m_progressBar->setColor(c);

  155. QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());

  156. m_colorBtn->setStyleSheet(styleCol);

  157. }

  158. }

  159.  
  160. void Widget::onWaterHeight(int value)

  161. {

  162. m_progressBar->setWaterHeight(double(value/1000.0));

  163. }

  164.  
  165. void Widget::onBorderWidth(int value)

  166. {

  167. m_progressBar->setBorderWidth(value);

  168. }

  169.  
  170. void Widget::onTextColorClicked()

  171. {

  172. QColor c = QColorDialog::getColor(m_progressBar->textColor());

  173. if(c.isValid()) {

  174. m_progressBar->setTextColor(c);

  175. QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());

  176. m_textColorBtn->setStyleSheet(styleCol);

  177. }

  178. }

  179.  
  180. void Widget::onBoderColorClicked()

  181. {

  182. QColor c = QColorDialog::getColor(m_progressBar->boderColor());

  183. if(c.isValid()) {

  184. m_progressBar->setBoderColor(c);

  185. QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());

  186. m_boderColorBtn->setStyleSheet(styleCol);

  187. }

  188. }

  189.  
  190. void Widget::onBgColorClicked()

  191. {

  192. QColor c = QColorDialog::getColor(m_progressBar->bgColor());

  193. if(c.isValid()) {

  194. m_progressBar->setBgColor(c);

  195. QString styleCol = QString("background-color:rgb(%0,%1,%2)").arg(c.red()).arg(c.green()).arg(c.blue());

  196. m_bgColorBtn->setStyleSheet(styleCol);

  197. }

  198. }

  199.  

猜你喜欢

转载自blog.csdn.net/wang13342322203/article/details/81979661