4

I'm able to do circular progressbar in qt while overriding paintEvent of the widget and draw circular progressbar but having a difficulty with the second circular progressbar (not able to draw like this) behind main circular progressbar:

enter image description here

Can anybody guide me through? Thanks beforehand.

Community
  • 1
  • 1
elgolondrino
  • 665
  • 9
  • 33

1 Answers1

9

I don't see what's the problem here, you can use QPainterPath and adding a full or partial arc path to it, then draw the path via QPen using a Qt::DotLine style.

If the stock dotted line doesn't work for you, there is the option to specify a custom pattern via:

void QPen::setDashPattern(const QVector<qreal> & pattern)

Here is a quick example, looking like this:

enter image description here

class CPBar : public QWidget {
    Q_OBJECT
    qreal p; // progress 0.0 to 1.0
  public:
    CPBar(QWidget * p = 0) : QWidget(p), p(0) {
      setMinimumSize(208, 208);
    }
    void upd(qreal pp) {
      if (p == pp) return;
      p = pp;
      update();
    }
  void paintEvent(QPaintEvent *) {
    qreal pd = p * 360;
    qreal rd = 360 - pd;
    QPainter p(this);
    p.fillRect(rect(), Qt::white);
    p.translate(4, 4);
    p.setRenderHint(QPainter::Antialiasing);
    QPainterPath path, path2;
    path.moveTo(100, 0);
    path.arcTo(QRectF(0, 0, 200, 200), 90, -pd);
    QPen pen, pen2;
    pen.setCapStyle(Qt::FlatCap);
    pen.setColor(QColor("#30b7e0"));
    pen.setWidth(8);
    p.strokePath(path, pen);
    path2.moveTo(100, 0);
    pen2.setWidth(8);
    pen2.setColor(QColor("#d7d7d7"));
    pen2.setCapStyle(Qt::FlatCap);
    pen2.setDashPattern(QVector<qreal>{0.5, 1.105});
    path2.arcTo(QRectF(0, 0, 200, 200), 90, rd);
    pen2.setDashOffset(2.2);
    p.strokePath(path2, pen2);
  }  
};

class Test : public QWidget {
    Q_OBJECT
  public:
    Test() {
      QVBoxLayout * l = new QVBoxLayout(this);
      CPBar * p = new CPBar;
      QSlider * s = new QSlider(Qt::Horizontal, this);
      s->setMinimum(0);
      s->setMaximum(100);
      l->addWidget(p);
      l->addWidget(s);
      setLayout(l);
      connect(s, &QSlider::valueChanged, [=](){ p->upd((qreal)s->value() / s->maximum());});
    }
};
dtech
  • 47,916
  • 17
  • 112
  • 190
  • This is how you achieve the result from the image. – dtech Mar 14 '17 at 19:26
  • I've only used `dashedPattern` but it gave me some circles in 360. They were bigger then I expected – elgolondrino Mar 14 '17 at 19:30
  • Don't have a experience with QPainterPath – elgolondrino Mar 14 '17 at 19:30
  • @elgolondrino see `QPainterPath::arcTo()` functions, which allow you to specify begin and end angle of the arc. http://doc.qt.io/qt-4.8/qpainterpath.html#arcTo – dtech Mar 14 '17 at 19:33
  • As I understand first I'm supposed to create `rectangle` e.g. `Trapezium`... and give coordinates to that function? – elgolondrino Mar 14 '17 at 19:37
  • What about button inside that progressBar, any ideas? – elgolondrino Mar 14 '17 at 19:40
  • 2
    I don't know what you are talking about, the format of usage is `arcTo(sizeRect, startAngle, lengthAngle)` - the size rect is the size of the circle, the rest is self explanatory. You obviously need to do more learning before you rush into making things. Read the documentation on `QPainter` and related types. – dtech Mar 14 '17 at 19:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138057/discussion-between-elgolondrino-and-ddriver). – elgolondrino Mar 14 '17 at 20:42