• 18483阅读
  • 16回复

Qt编写动态圆形进度条 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2016-10-14
最近在整理用户自定义控件,包含开源的和修正的及自己写的。
参照Qt自己的命名,统一定义了一些书写规范:

1:所有命名均为首字母小写,例如setValue;
2:私有变量及函数不建议使用下划线;
3:设置用set开头,获取值用get开头;
4:公共方法和公有槽都要注释,私有的变量和方法建议注释。
5:方法及变量类似的含义的,可以靠在一起分组,不同分组间空一行。
6:所有公共方法,函数体超过一行的在头文件中只声明,实现文件中写具体方法。
7:void类型的公共方法全部改为公共槽。

头文件依次排列顺序:
public:构造函数及析构函数
protected:重写的方法,例如paintEvent等。
private:私有变量
private slots:私有槽函数
public:公共方法
public slots:公有槽函数
signal:信号

  1. #ifndef ROUNDPLOT_H
  2. #define ROUNDPLOT_H
  3. #include <QWidget>
  4. /**
  5. * 作者:feiyangqingyun(QQ:517216493) 2016-10-14
  6. * 本控件来源于网络(原作者:不详),本人重写90%的代码
  7. */
  8. class RoundPlot : public QWidget
  9. {
  10.     Q_OBJECT
  11. public:
  12.     RoundPlot(QWidget *parent = 0);
  13.     ~RoundPlot();
  14. protected:
  15.     void paintEvent(QPaintEvent *event);
  16. private:
  17.     int minValue;               //最小值
  18.     int maxValue;               //最大值
  19.     int value;                  //目标值
  20.     QString unit;               //单位
  21.     int currentValue;           //当前值
  22.     int step;                   //步长,动态变化时每次增加的步长
  23.     QColor usedColor;           //已使用百分比颜色
  24.     QColor freeColor;           //未使用百分比颜色
  25.     QColor rangeTextColor;      //范围值文字颜色
  26.     QColor valueTextColor;      //目标值文字颜色
  27.     QColor valueBgColor;        //目标值背景色
  28.     QColor outBgColor;          //外边框背景色
  29.     QColor centerBgColorStart;  //中间圆环渐变背景起始颜色
  30.     QColor centerBgColorEnd;    //中间圆环渐变背景结束颜色
  31.     QFont rangeTextFont;        //范围值文字字体
  32.     QFont valueTextFont;        //目标值文字字体
  33.     QTimer *updateTimer;        //绘制定时器
  34. private slots:
  35.     void updateValue();
  36. public:
  37.     //获取最小值
  38.     int getMinValue()const
  39.     {
  40.         return minValue;
  41.     }
  42.     //获取最大值
  43.     int getMaxValue()const
  44.     {
  45.         return maxValue;
  46.     }
  47.     //获取目标值
  48.     int getValue()const
  49.     {
  50.         return value;
  51.     }
  52.     //获取单位
  53.     QString getUnit()const
  54.     {
  55.         return unit;
  56.     }
  57. public slots:
  58.     //设置最大最小值-范围值
  59.     void setRange(int minValue, int maxValue);
  60.     //设置目标值
  61.     void setValue(int value);
  62.     //设置文字后面的单位
  63.     void setUnit(QString unit);
  64.     //设置已使用百分比颜色
  65.     void setUsedColor(QColor usedColor);
  66.     //设置未使用百分比颜色
  67.     void setFreeColor(QColor freeColor);
  68.     //设置范围值文字颜色
  69.     void setRangeTextColor(QColor rangeTextColor);
  70.     //设置目标值文字颜色
  71.     void setValueTextColor(QColor valueTextColor);
  72.     //设置目标值背景色
  73.     void setValueBgColor(QColor valueBgColor);
  74.     //设置外边框背景色
  75.     void setOutBgColor(QColor outBgColor);
  76.     //设置中央圆形背景色
  77.     void setCenterBgColor(QColor centerBgColorStart, QColor centerBgColorEnd);
  78.     //设置范围值文字字体
  79.     void setRangeTextFont(QFont rangeTextFont);
  80.     //设置目标值文字字体
  81.     void setValueTextFont(QFont valueTextFont);    
  82. };
  83. #endif // ROUNDPLOT_H

  1. #include "roundplot.h"
  2. #include "qtimer.h"
  3. #include "qpainter.h"
  4. #include "qapplication.h"
  5. #include "qevent.h"
  6. #include "qdesktopwidget.h"
  7. #include "qdebug.h"
  8. RoundPlot::RoundPlot(QWidget *parent)
  9.     : QWidget(parent, Qt::FramelessWindowHint)
  10. {
  11.     setMinimumSize(167, 167);
  12.     setAutoFillBackground(true);
  13.     QPalette palette = this->palette();
  14.     palette.setColor(QPalette::Background, QColor(255, 255, 255));
  15.     setPalette(palette);
  16.     minValue = 0;
  17.     maxValue = 100;
  18.     value = 0;
  19.     unit = "";
  20.     currentValue = 0;
  21.     step = maxValue / 100;    
  22.     usedColor = QColor(165, 220, 62);
  23.     freeColor = QColor(215, 215, 215);
  24.     rangeTextColor = QColor(137, 137, 137);
  25.     valueTextColor = QColor(52, 155, 218);
  26.     valueBgColor = QColor(239, 239, 239);
  27.     outBgColor = QColor(233, 233, 233);
  28.     centerBgColorStart = QColor(45, 204, 112);
  29.     centerBgColorEnd = QColor(51, 152, 219);
  30.     rangeTextFont = QFont("Arial", 10, QFont::Normal);
  31.     valueTextFont = QFont("Arial", 15, QFont::Bold);    
  32.     updateTimer = new QTimer(this);
  33.     updateTimer->setInterval(10);
  34.     connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateValue()));
  35. }
  36. RoundPlot::~RoundPlot()
  37. {
  38.     if (updateTimer->isActive()) {
  39.         updateTimer->stop();
  40.     }
  41. }
  42. void RoundPlot::paintEvent(QPaintEvent *event)
  43. {
  44.     Q_UNUSED(event)
  45.     int width = this->width();
  46.     int height = this->height();
  47.     //直径取宽高中最短的一个
  48.     int diameter = width > height ? height : width;
  49.     //绘制准备工作,旋转坐标轴中心
  50.     QPainter painter(this);
  51.     painter.setRenderHint(QPainter::Antialiasing);
  52.     painter.setRenderHint(QPainter::SmoothPixmapTransform);
  53.     painter.translate(width / 2, height / 2);
  54.     painter.save();
  55.     painter.rotate(40);
  56.     //自动计算比例关系
  57.     double percent = (double)100 / (maxValue - minValue);
  58.     int currentPercent = currentValue * percent;
  59.     int maxPercent = maxValue * percent;
  60.     //自动计算位置比例
  61.     double diameterLine = ((double)3 / 167) * diameter;
  62.     double diameterWidth = ((double)70 / 167) * diameter;
  63.     double diameterHeight = ((double)80 / 167) * diameter;
  64.     double diameter1 = ((double)55 / 167) * diameter;
  65.     double diameter2 = ((double)35 / 167) * diameter;
  66.     double diameter3 = ((double)30 / 167) * diameter;
  67.     double diameter4 = ((double)80 / 167) * diameter;
  68.     double diameter5 = ((double)135 / 167) * diameter;
  69.     //绘制当前百分比
  70.     painter.setPen(QPen(usedColor, diameterLine));
  71.     for (int i = minValue; i < currentPercent; i++) {
  72.         painter.drawLine(0, diameterWidth, 0, diameterHeight);
  73.         painter.rotate(2.8);
  74.     }
  75.     //绘制空余百分比
  76.     painter.setPen(QPen(freeColor, diameterLine));
  77.     for (int i = currentPercent; i < maxPercent; i++) {
  78.         painter.drawLine(0, diameterWidth, 0, diameterHeight);
  79.         painter.rotate(2.8);
  80.     }
  81.     painter.restore();
  82.     //绘制最外框圆形背景
  83.     painter.translate(-width / 2, -height / 2);
  84.     painter.setBrush(outBgColor);
  85.     painter.setPen(QPen(outBgColor, 15));
  86.     painter.drawEllipse(QRectF((width / 2 - diameter1), (height / 2 - diameter1), diameter1 * 2, diameter1 * 2));
  87.     //绘制中间框圆形渐变背景
  88.     QConicalGradient conicalGradient(width / 2, height / 2, 90);
  89.     conicalGradient.setColorAt(0, centerBgColorStart);
  90.     conicalGradient.setColorAt(1.0, centerBgColorEnd);
  91.     painter.setPen(QPen(QBrush(conicalGradient), 30));
  92.     painter.drawEllipse(QRectF((width / 2 - diameter2), (height / 2 - diameter2), diameter2 * 2, diameter2 * 2));
  93.     //绘制最里框百分比文字圆形背景
  94.     painter.setPen(Qt::NoPen);
  95.     painter.setBrush(valueBgColor);
  96.     painter.drawEllipse(QRectF((width / 2 - diameter3), (height / 2 - diameter3), diameter3 * 2, diameter3 * 2));
  97.     //绘制百分比文字及范围值文字
  98.     painter.setPen(QPen(valueTextColor));
  99.     painter.setFont(valueTextFont);
  100.     painter.drawText(0, 0, width, height, Qt::AlignCenter, tr("%1%2").arg(currentValue).arg(unit));
  101.     painter.setPen(QPen(rangeTextColor));
  102.     painter.setFont(rangeTextFont);
  103.     painter.drawText(0, 0, width - diameter4, height + diameter5, Qt::AlignCenter, tr("%1%2").arg(minValue).arg(unit));
  104.     painter.drawText(0, 0, width + diameter4, height + diameter5, Qt::AlignCenter, tr("%1%2").arg(maxValue).arg(unit));
  105. }
  106. void RoundPlot::updateValue()
  107. {
  108.     if (currentValue >= value) {
  109.         updateTimer->stop();
  110.         return;
  111.     }
  112.     currentValue = currentValue + step;
  113.     update();
  114. }
  115. void RoundPlot::setRange(int minValue, int maxValue)
  116. {
  117.     if (updateTimer->isActive()) {
  118.         updateTimer->stop();
  119.     }
  120.     currentValue = minValue;
  121.     this->minValue = minValue;
  122.     this->maxValue = maxValue;
  123.     //如果目标值不在范围值内,则重新设置目标值
  124.     if (value < minValue || value > maxValue) {
  125.         setValue(value);
  126.     }
  127.     //自动计算步长,步长=最大值/100
  128.     step = maxValue / 100;
  129. }
  130. void RoundPlot::setValue(int value)
  131. {
  132.     //如果目标值比最小值小则取最小值,如果目标值比最大值大则取最大值
  133.     if (value < minValue) {
  134.         this->value = minValue;
  135.     } else if (value > maxValue) {
  136.         this->value = maxValue;
  137.     } else {
  138.         this->value = value;
  139.     }
  140.     updateTimer->start();
  141. }
  142. void RoundPlot::setUnit(QString unit)
  143. {
  144.     this->unit = unit;
  145.     update();
  146. }
  147. void RoundPlot::setUsedColor(QColor usedColor)
  148. {
  149.     this->usedColor = usedColor;
  150.     update();
  151. }
  152. void RoundPlot::setFreeColor(QColor freeColor)
  153. {
  154.     this->freeColor = freeColor;
  155.     update();
  156. }
  157. void RoundPlot::setRangeTextColor(QColor rangeTextColor)
  158. {
  159.     this->rangeTextColor = rangeTextColor;
  160.     update();
  161. }
  162. void RoundPlot::setValueTextColor(QColor valueTextColor)
  163. {
  164.     this->valueTextColor = valueTextColor;
  165.     update();
  166. }
  167. void RoundPlot::setValueBgColor(QColor valueBgColor)
  168. {
  169.     this->valueBgColor = valueBgColor;
  170.     update();
  171. }
  172. void RoundPlot::setOutBgColor(QColor outBgColor)
  173. {
  174.     this->outBgColor = outBgColor;
  175.     update();
  176. }
  177. void RoundPlot::setCenterBgColor(QColor centerBgColorStart, QColor centerBgColorEnd)
  178. {
  179.     this->centerBgColorStart = centerBgColorStart;
  180.     this->centerBgColorEnd = centerBgColorEnd;
  181.     update();
  182. }
  183. void RoundPlot::setRangeTextFont(QFont rangeTextFont)
  184. {
  185.     this->rangeTextFont = rangeTextFont;
  186.     update();
  187. }
  188. void RoundPlot::setValueTextFont(QFont valueTextFont)
  189. {
  190.     this->valueTextFont = valueTextFont;
  191.     update();
  192. }

使用方法:
  1. #include "frmroundplot.h"
  2. #include "ui_frmroundplot.h"
  3. #include "myhelper.h"
  4. #include "control/roundplot.h"
  5. frmRoundPlot::frmRoundPlot(QWidget *parent) :
  6.     QWidget(parent),
  7.     ui(new Ui::frmRoundPlot)
  8. {
  9.     ui->setupUi(this);
  10.     ui->widget2->setUsedColor(QColor(41, 137, 219));
  11.     ui->widget2->setFreeColor(QColor(50, 50, 50));
  12.     ui->widget2->setRangeTextColor(QColor(103, 103, 103));
  13.     ui->widget2->setValueTextColor(QColor(250, 250, 250));
  14.     ui->widget2->setValueBgColor(QColor(45, 169, 222));
  15.     ui->widget2->setOutBgColor(QColor(202, 225, 255));
  16.     ui->widget2->setCenterBgColor(QColor(67, 205, 128), QColor(60, 179, 113));
  17.     ui->widget2->setRangeTextFont(QFont("Microsoft Yahei", 10, QFont::Normal));
  18.     ui->widget2->setValueTextFont(QFont("Microsoft Yahei", 18, QFont::Normal));
  19.     on_pushButton_clicked();
  20. }
  21. frmRoundPlot::~frmRoundPlot()
  22. {
  23.     delete ui;
  24. }
  25. void frmRoundPlot::on_pushButton_clicked()
  26. {
  27.     int min = ui->txtMin->text().toInt();
  28.     int max = ui->txtMax->text().toInt();
  29.     int current = ui->txtCurrent->text().toInt();
  30.     QString unit = ui->txtUnit->text();
  31.     ui->widget1->setRange(min, max);
  32.     ui->widget2->setRange(min, max);
  33.     ui->widget1->setValue(current);
  34.     ui->widget2->setValue(current);
  35.     ui->widget1->setUnit(unit);
  36.     ui->widget2->setUnit(unit);
  37. }
效果

欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线仗剑天涯

只看该作者 1楼 发表于: 2016-10-14
大神新品,赞一个

只看该作者 2楼 发表于: 2016-10-14
大神,膜拜学习!
离线listen342325

只看该作者 3楼 发表于: 2016-10-14
最小大小167,这个可不可以改?
Qt 不错的选择
离线liudianwu

只看该作者 4楼 发表于: 2016-10-14
回 listen342325 的帖子
listen342325:最小大小167,这个可不可以改? (2016-10-14 14:50) 

肯定可以改的。
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线crazy

只看该作者 5楼 发表于: 2016-10-16
        
C/C++/Qt爱好者
邮箱: kevinlq0912@163.com
公众号: devstone
博客:http://kevinlq.com/
离线disongshu

只看该作者 6楼 发表于: 2016-10-17
    

只看该作者 7楼 发表于: 2016-10-18
膜拜大神新作

只看该作者 8楼 发表于: 2016-10-24
大神,你真实我在Qt上的指路人啊
离线mu_de_yu

只看该作者 9楼 发表于: 2017-01-17
    
离线mu_de_yu

只看该作者 10楼 发表于: 2017-01-17
    
离线panfan

只看该作者 11楼 发表于: 2017-01-18
            
博观而约取,厚积而薄发
离线tedboston

只看该作者 12楼 发表于: 2017-01-18
怎么没有这个Qroundplot类啊
离线zwk0704

只看该作者 13楼 发表于: 2017-04-11

先赞再看
离线zwk0704

只看该作者 14楼 发表于: 2017-04-12
反馈:
1.采用定时器绘制,如果数值过大,不处理直接输入,耗时,对程序其他运行程序不好
2.不能小数显示,当然楼主也说了是进度,不过也应该考虑小数
P.S
上述问题在楼组下一篇博文得到了解决,赞
离线iehttp

只看该作者 15楼 发表于: 2017-05-08
神赞一下
离线a798213343

只看该作者 16楼 发表于: 2020-12-09
请问可以使用qml去实现吗
快速回复
限100 字节
 
上一个 下一个