Search code examples
c++qtqt5qprogressbar

How to get a cylinder effect (2D) Progress Bar using Qt programming?


How to change the colors of the progressbar? Say 40% to red, 20% to green and 40% to yellow etc. I have tried using StyleSheets, but I found that it works only for Flat Progress Bars , not for the 2D bars.

enter image description here


Solution

  • To be able to generate this effect we draw elliptical, for this we could help us of QPainterPath to give it form, and we put the cover that is an ellipse as shown below:

    progressbar2d.h

    #ifndef PROGRESSBAR2D_H
    #define PROGRESSBAR2D_H
    
    #include <QProgressBar>
    
    class ProgressBar2D : public QProgressBar
    {
        Q_OBJECT
    
    public:
        ProgressBar2D(QWidget *parent = 0);
        ~ProgressBar2D();
    
    protected:
        void paintEvent(QPaintEvent *);
    
    private:
        void draw(QPainter *painter, QRect rect, int w);
        void drawEllipticalRectangle(QPainter *painter, QRect rect, int w);
    };
    
    #endif // PROGRESSBAR2D_H
    

    progressbar2d.cpp

    #include "progressbar2d.h"
    #include <QPainter>
    
    ProgressBar2D::ProgressBar2D(QWidget *parent): QProgressBar(parent)
    {
    }
    
    ProgressBar2D::~ProgressBar2D()
    {
    }
    
    void ProgressBar2D::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
    
        int borde = height()/10;
    
        draw(&painter,
             QRect(borde, borde, width()-2*borde, height()-2*borde),
             2*borde);
    
        painter.drawText(rect(),  Qt::AlignCenter, QString("%1").arg(value()));
    
    }
    
    void ProgressBar2D::draw(QPainter *painter, QRect rect, int w)
    {
    
        int w_percentage = 2*w + value()*(rect.width()-2*w)/maximum();
    
        painter->setBrush(QBrush(QColor("#81C253")));
        drawEllipticalRectangle(painter,
                                QRect(rect.topLeft(), QSize(w_percentage, rect.height()) ),
                                w);
    
        painter->setBrush(QBrush(QColor("#C3DDB1")));
        drawEllipticalRectangle(painter,
                                QRect(QPoint(rect.topLeft() + QPoint(w_percentage-2*w, 0)),
                                      QSize(rect.width()-w_percentage+2*w, rect.height()) ),
                                w);
    
        painter->setBrush(QBrush(QColor("#77896C")));
        painter->drawEllipse(QRect( rect.topLeft() + QPoint(rect.width()-2*w, 0) , QSize(2*w, rect.height())));
    
    }
    
    
    void ProgressBar2D::drawEllipticalRectangle(QPainter *painter, QRect rect, int w)
    {
        painter->translate(rect.topLeft());
    
        QPainterPath path;
    
        path.moveTo(w, 0);
        path.arcTo(QRectF(0, 0, 2*w, rect.height()), 90, 180);
        path.lineTo(rect.width()-w, rect.height());
    
        path.arcTo(QRectF(rect.width()-2*w, 0, 2*w, rect.height()), 270, -180);
        path.lineTo(w, 0);
        painter->drawPath(path);
    
        painter->translate(-rect.topLeft());
    }
    

    main.cpp

    #include "progressbar2d.h"
    #include <QApplication>
    #include <QTimer>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        ProgressBar2D w;
    
        QTimer *timer = new QTimer(&w);
    
        QObject::connect(timer, &QTimer::timeout, [&w](){
            w.setValue((w.value()+1)%(1 + w.maximum()));
        });
        timer->start(100);
        w.show();
    
        return a.exec();
    }
    

    enter image description here