Qt 圆形进度条实现

分手后的思念是犯贱 2023-06-08 09:25 127阅读 0赞

1.运行截图

20191017181959480.gif20191017182024918.gif20191017182041705.gif

2.源码

  1. .h
  2. #ifndef _QROUNDPROGRESSBAR_H_
  3. #define _QROUNDPROGRESSBAR_H_
  4. #include <QWidget>
  5. class QRoundProgressBar : public QWidget
  6. {
  7. Q_OBJECT
  8. //进度条形状
  9. enum BarStyle
  10. {
  11. //圆环状
  12. StyleDonut = 0,
  13. //圆饼状
  14. StylePie,
  15. //圆线状
  16. StyleLine
  17. };
  18. public:
  19. QRoundProgressBar(QWidget *parent , BarStyle style = StyleLine);
  20. ~QRoundProgressBar();
  21. public:
  22. //设置扫描弧度起始角度
  23. void setStartAngle(double position);
  24. //设置轮廓画笔的宽度
  25. void setOutlinePenWidth(double penWidth);
  26. //设置画笔宽度
  27. void setDataPenWidth(double penWidth);
  28. //设置进度条精度 88.88%,几位小数
  29. void setDecimals(int count);
  30. //设置进度条风格
  31. void setBarStyle(BarStyle style);
  32. //设置范围
  33. void setRange(double min, double max);
  34. //设置当前值
  35. void setValue(int val);
  36. //设置当前值
  37. void setValue(double val);
  38. //设置最小值
  39. void setMinimum(double min);
  40. //设置最大值
  41. void setMaximum(double max);
  42. protected:
  43. void paintEvent(QPaintEvent *event);
  44. //画基础图形
  45. void drawBase(QPainter& p, const QRectF& baseRect, const QRectF &innerRect);
  46. //根据值画出进度条
  47. void drawValue(QPainter& p, const QRectF& baseRect, double value, double arcLength, const QRectF & innerRect
  48. , double innerDiameter);
  49. //画中心文字
  50. void drawText(QPainter& p, const QRectF& innerRect, double value);
  51. private:
  52. double m_min; //最小值
  53. double m_max; //最大值
  54. double m_value; //当前值
  55. BarStyle m_barStyle; //进度条风格
  56. int m_decimals; //进度条精度
  57. double m_startAngel; //扫描弧度起始角度
  58. double m_outlinePenWidth; //轮廓画笔的宽度
  59. double m_dataPenWidth; //画笔宽度
  60. };
  61. #endif // _QROUNDPROGRESSBAR_H_
  62. .cpp
  63. #include "QRoundProgressBar.h"
  64. #include <QPainter>
  65. #include <QPointF>
  66. #include <QtMath>
  67. QRoundProgressBar::QRoundProgressBar(QWidget *parent , BarStyle style)
  68. : QWidget(parent)
  69. , m_min(0)
  70. , m_max(100)
  71. , m_value(0)
  72. , m_startAngel(90)
  73. , m_barStyle(style)
  74. , m_outlinePenWidth(0)
  75. , m_dataPenWidth(0)
  76. , m_decimals(0)
  77. {
  78. }
  79. QRoundProgressBar::~QRoundProgressBar()
  80. {
  81. }
  82. void QRoundProgressBar::setStartAngle(double angle)
  83. {
  84. if (angle != m_startAngel)
  85. {
  86. m_startAngel = angle;
  87. update();
  88. }
  89. }
  90. void QRoundProgressBar::setOutlinePenWidth(double penWidth)
  91. {
  92. if (penWidth != m_outlinePenWidth)
  93. {
  94. m_outlinePenWidth = penWidth;
  95. update();
  96. }
  97. }
  98. void QRoundProgressBar::setDataPenWidth(double penWidth)
  99. {
  100. if (penWidth != m_dataPenWidth)
  101. {
  102. m_dataPenWidth = penWidth;
  103. update();
  104. }
  105. }
  106. void QRoundProgressBar::setDecimals(int count)
  107. {
  108. if (count >= 0 && count != m_decimals)
  109. {
  110. m_decimals = count;
  111. update();
  112. }
  113. }
  114. void QRoundProgressBar::setBarStyle(BarStyle style)
  115. {
  116. if (style != m_barStyle)
  117. {
  118. m_barStyle = style;
  119. update();
  120. }
  121. }
  122. void QRoundProgressBar::setRange(double min, double max)
  123. {
  124. m_min = min;
  125. m_max = max;
  126. if (m_max < m_min)
  127. {
  128. qSwap(m_max, m_min);
  129. }
  130. if (m_value < m_min)
  131. {
  132. m_value = m_min;
  133. }
  134. else if (m_value > m_max)
  135. {
  136. m_value = m_max;
  137. }
  138. update();
  139. }
  140. void QRoundProgressBar::setValue(double val)
  141. {
  142. if (m_value != val)
  143. {
  144. if (val < m_min)
  145. {
  146. m_value = m_min;
  147. }
  148. else if (val > m_max)
  149. {
  150. m_value = m_max;
  151. }
  152. else
  153. {
  154. m_value = val;
  155. }
  156. update();
  157. }
  158. }
  159. void QRoundProgressBar::setValue(int val)
  160. {
  161. setValue(double(val));
  162. }
  163. void QRoundProgressBar::setMinimum(double min)
  164. {
  165. setRange(min, m_max);
  166. }
  167. void QRoundProgressBar::setMaximum(double max)
  168. {
  169. setRange(m_min, max);
  170. }
  171. void QRoundProgressBar::paintEvent(QPaintEvent* /*event*/)
  172. {
  173. //外圈直径
  174. double outerDiameter = this->width();
  175. //外圈矩形
  176. QRectF baseRect(0, 0, outerDiameter, outerDiameter);
  177. QPainter p(this);
  178. p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
  179. //画背景矩形填充白色
  180. p.fillRect(baseRect, QBrush(QColor("#FFFFFF")));
  181. //内圆直径
  182. double innerDiameter;
  183. //内圈矩形
  184. QRectF innerRect;
  185. //计算内圈矩形
  186. if (m_barStyle == StyleLine)
  187. {
  188. innerDiameter = outerDiameter - m_outlinePenWidth;
  189. }
  190. else if(m_barStyle == StyleDonut)
  191. {
  192. innerDiameter = outerDiameter * 0.9;
  193. }
  194. double delta = (outerDiameter - innerDiameter) / 2;
  195. innerRect = QRectF(delta, delta, innerDiameter, innerDiameter);
  196. //画基础图形
  197. drawBase(p, baseRect, innerRect);
  198. //计算当前步长比例
  199. double arcStep = 360.0 / (m_max - m_min) * m_value;
  200. //根据值画出进度条
  201. drawValue(p, baseRect, m_value, arcStep, innerRect, innerDiameter);
  202. //画文字
  203. drawText(p, baseRect, m_value);
  204. p.end();
  205. }
  206. void QRoundProgressBar::drawBase(QPainter &p, const QRectF &baseRect, const QRectF &innerRect)
  207. {
  208. switch (m_barStyle)
  209. {
  210. case StyleDonut:
  211. {
  212. QPainterPath dataPath;
  213. dataPath.setFillRule(Qt::OddEvenFill);
  214. dataPath.moveTo(baseRect.center());
  215. dataPath.addEllipse(innerRect);
  216. QPen pen;
  217. pen.setColor(QColor("#DEE3E7"));
  218. pen.setWidth(10);
  219. p.setPen(pen);
  220. p.setBrush(QBrush(QColor("#FFFFFF")));
  221. p.drawPath(dataPath);
  222. break;
  223. }
  224. case StylePie:
  225. {
  226. p.setPen(QPen(QColor("#FFFFFF"), m_outlinePenWidth));
  227. p.setBrush(QBrush(QColor("#DEE3E7")));
  228. p.drawEllipse(baseRect);
  229. break;
  230. }
  231. case StyleLine:
  232. {
  233. p.setPen(QPen(QColor("#FFFFFF"), m_outlinePenWidth));
  234. p.setBrush(Qt::NoBrush);
  235. p.drawEllipse(baseRect.adjusted(m_outlinePenWidth / 2, m_outlinePenWidth / 2, -m_outlinePenWidth / 2, -m_outlinePenWidth / 2));
  236. break;
  237. }
  238. default:
  239. {
  240. break;
  241. }
  242. }
  243. }
  244. void QRoundProgressBar::drawValue(QPainter &p, const QRectF &baseRect , double value, double arcLength
  245. , const QRectF & innerRect, double innerDiameter)
  246. {
  247. if (value == m_min)
  248. {
  249. return;
  250. }
  251. if (m_barStyle == StyleLine)
  252. {
  253. p.setPen(QColor("#2F8DED"));
  254. p.setBrush(Qt::NoBrush);
  255. p.drawArc(baseRect,m_startAngel * 16, -arcLength * 16);
  256. }
  257. else if (m_barStyle == StyleDonut)
  258. {
  259. QPen pen;
  260. pen.setColor(QColor("#2F8DED"));
  261. pen.setWidth(10);
  262. pen.setCapStyle(Qt::RoundCap);
  263. p.setPen(pen);
  264. p.drawArc(innerRect, m_startAngel*16 , -16*arcLength);
  265. }
  266. else
  267. {
  268. //获取中心点坐标
  269. QPointF centerPoint = baseRect.center();
  270. QPainterPath dataPath;
  271. dataPath.setFillRule(Qt::WindingFill);
  272. dataPath.moveTo(centerPoint);
  273. //逆时针画弧长
  274. dataPath.arcTo(baseRect, m_startAngel, -arcLength);
  275. if (m_barStyle == StylePie)
  276. {
  277. dataPath.lineTo(centerPoint);
  278. p.setPen(QPen(QColor("#2F8DED"), m_dataPenWidth));
  279. }
  280. p.setBrush(QBrush(QColor("#2F8DED")));
  281. p.drawPath(dataPath);
  282. }
  283. }
  284. void QRoundProgressBar::drawText(QPainter &p, const QRectF &rect, double value)
  285. {
  286. QString textToDraw = "%";
  287. double percent = (value - m_min) / (m_max - m_min) * 100.0;
  288. textToDraw = QString::number(percent, 'f', m_decimals) + textToDraw;
  289. QFont f;
  290. f.setFamily("微软雅黑");
  291. f.setPixelSize(20);
  292. p.setFont(f);
  293. p.setPen(QColor("#606266"));
  294. p.drawText(rect, Qt::AlignCenter, textToDraw);
  295. }

发表评论

表情:
评论列表 (有 0 条评论,127人围观)

还没有评论,来说两句吧...

相关阅读

    相关 WPF圆形进度制作

        WPF和Winform都为我们提供了ProgressBar进度条。但是这种死板的进度条已经不能满足用户对美的要求了。因此,本篇文章要为大家展示一种圆形进度条。    

    相关 自定义圆形进度

    自定义圆形进度条:自己写的一个类 ,使用非常简单,非常适合新手学习。 (因为我就是新手,通过学了这个之后,以后绘制其他的图也是差不多这样,能够做到举一反三!事半功倍!非常值得