如何使用Qt编程获得圆柱效果(2D)进度条?

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

如何改变进度条的颜色?比如说 40% 给红色,20% 给绿色,40% 给黄色等等。 我尝试过使用 StyleSheets,但我发现它仅适用于 Flat Progress Bars ,不适用于 2D 条。

为了产生这个效果我们画了椭圆形,为此我们可以帮QPainterPath给它定型,我们把它作为椭圆的封面如下图:

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();
}