Adil Ahmed Adil Ahmed - 2 months ago 20
C++ Question

Progress Bar Colors

I need my

QProgressBar
to change color on specific values, such as


  • 0-60 Int portion : Green

  • 60-80 Int : Orange

  • 80-100 Int : Red



but I can't find the solution. From style sheet the whole color of progress bar changes on values but not portion wise.

I am using
QT creator 3.4.0
based on
QT 5.4.1
.

Answer

You can do it with stylesheets like this:

QProgressBar* bar = new QProgressBar();
bar->setStyleSheet("::chunk {"
                   "background-color: "
                   "qlineargradient(x0: 0, x2: 1, "
                   "stop: 0 green, stop: 0.6 green, "
                   "stop: 0.60001 orange, stop: 0.8 orange, "
                   "stop: 0.80001 red, stop: 1 red"
                   ")}");

It will look like this:

enter image description here

You can make it smoother simply applying this:

 bar->setStyleSheet("::chunk {"
                    "background-color: "
                    "qlineargradient(x0: 0, x2: 1, "
                    "stop: 0 green, stop: 0.6 green, "
                    "stop: 0.8 orange, "
                    "stop: 1 red"
                    ")}");

enter image description here

Update:

this solution isn't correct, since with values less than maximum you'll get something like this:

enter image description here

As pointed out by others, and here: Gradient for chunks in QProgressBar

the only solution seems to customize the paintEvent

Update2:

Just for completeness, here the relevant code for custom paintEvent. This will work, but it doesn't look very good. Also, most parameters should be class members and set by the user. However:

coloredprogressbar.h

#ifndef COLOREDPROGRESSBAR_H
#define COLOREDPROGRESSBAR_H

#include <QWidget>
#include <QProgressBar>
#include <QPaintEvent>

class ColoredProgressBar : public QProgressBar
{
    Q_OBJECT
public:
    explicit ColoredProgressBar(QWidget *parent = 0);
    ~ColoredProgressBar();

protected:

    void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;

signals:

public slots:
};

#endif // COLOREDPROGRESSBAR_H

coloredprogressbar.cpp

#include "coloredprogressbar.h"

#include <QPainter>
#include <QBrush>
#include <QStyle>
#include <QPen>
#include <QColor>

ColoredProgressBar::ColoredProgressBar(QWidget *parent) : QProgressBar(parent)
{

}

ColoredProgressBar::~ColoredProgressBar()
{

}

void ColoredProgressBar::paintEvent(QPaintEvent*)
{
    int val = value();
    int pos = QStyle::sliderPositionFromValue(minimum(), maximum(), val, width());

    int pos60 = QStyle::sliderPositionFromValue(minimum(), maximum(), 60, width());
    int pos80 = QStyle::sliderPositionFromValue(minimum(), maximum(), 80, width());

    QPainter p(this);
    p.setPen(Qt::green);
    p.setBrush(QBrush(Qt::green));

    if(val >= 0 && val <= 60)
    {
        p.drawRect(0,0,pos,height());
    }
    else if(val > 60 && val <= 80)
    {
        p.drawRect(0,0,pos60,height());
        p.setPen(QColor(255,127,0));
        p.setBrush(QBrush(QColor(255,127,0)));
        p.drawRect(pos60, 0, pos - pos60, height());
    }
    else
    {
        p.drawRect(0,0,pos60,height());
        p.setPen(QColor(255,127,0));
        p.setBrush(QBrush(QColor(255,127,0)));
        p.drawRect(pos60, 0, pos80 - pos60,height());
        p.setPen(Qt::red);
        p.setBrush(QBrush(Qt::red));
        p.drawRect(pos80, 0, pos - pos80, height());
    }

    p.setPen(Qt::lightGray);
    p.setBrush(QBrush(Qt::lightGray));
    p.drawRect(pos, 0, width(), height());


    p.setPen(Qt::black);
    p.setBrush(QBrush(Qt::black));
    p.drawText(0,0, width(), height(), Qt::AlignCenter, QString::number(val) + "%");
}

usage

#include <QApplication>
#include "coloredprogressbar.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    ColoredProgressBar bar;
    bar.setValue(85);
    bar.show();

    return a.exec();
}

I repeat, this is just a simple implementation that doesn't look good and misses some user-settable features, but could be a place to start. Feel free to edit this code.

Comments