css 进度条颜色

pgvzfuti  于 2023-03-25  发布在  其他
关注(0)|答案(7)|浏览(139)

我需要我的QProgressBar来更改特定值的颜色,例如

  • 0-60整数部分:绿色
  • 60-80 Int:橙子
  • 80-100整数:红色

但是我找不到解决办法。从样式表中,进度条的整个颜色会根据值而改变,但不会部分改变。
我使用基于QT 5.4.1QT creator 3.4.0

smtd7mpg

smtd7mpg1#

你可以这样使用样式表:

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

它看起来像这样:

你可以简单地使用这个来使它更平滑:

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

更新:

这个解决方案是不正确的,因为如果值小于最大值,你会得到这样的结果:

正如其他人和这里所指出的:Gradient for chunks in QProgressBar
唯一的解决方案似乎是自定义paintEvent

更新二:

为了完整起见,这里是自定义paintEvent的相关代码。这将工作,但看起来不是很好。此外,大多数参数应该是类成员并由用户设置。然而:

彩色进度条.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) + "%");
}

用法

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

我重复一遍,这只是一个简单的实现,看起来不太好,缺少一些用户可设置的功能,但可以作为一个起点。请随意编辑此代码。

sshcrbum

sshcrbum2#

我发现了一个可以使用样式表的解决方案,尽管它不是很灵活。你可以设置QProgressBar的背景而不是块,然后使用反转的外观:

QProgressBar.setInvertedAppearance(True)

上面的命令是针对PyQt 5的,所以看看c++的正确命令。使用下面的样式表,我使用的渐变是垂直进度条,所以需要一些调整来使其水平正确。在这种情况下,也使用width:而不是height:

QProgressBar{
    border: 2px solid grey;
    border-radius: 3px;
    text-align: center;
    background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, 
                               stop:0 rgba(0, 170, 0, 255), stop:0.33 rgba(255, 255, 0, 255),
                               stop:0.6 rgba(232, 165, 0, 255), stop:1 rgba(189, 0, 0, 255));
}

QProgressBar::chunk {
    background-color: rgb(50,50,50);
    margin: 0px;
    height: 5px;
}

这样做的一个限制是你不能使用带边距的块,而且你必须反转你为进度设置的值。所以100变成0,70变成30,等等。
你可以通过设置块的高度为0.5px这样的小值来使用它作为一个连续的进度条。希望它可以节省一些人子类化QProgressBar和实现painter的麻烦!

yqkkidmi

yqkkidmi3#

你不能用现有的样式表属性来实现你想要的效果,但是你可以子类化QProgressBar并重新实现paint来获得你想要的外观。

gmol1639

gmol16394#

正如@Gabriel de Grimouard已经提到的,您需要对QProgressBar进行子类化并重新实现paint,但是还有另一种方法(可能有点脏,但是很快)--对QProgressBar进行子类化并修改setValue slot。

QString style_0_60      = "QProgressBar::chunk{ background-color: green; }";
QString style_60_80     = "QProgressBar::chunk{ background-color: orange; }";
QString style_80_100    = "QProgressBar::chunk{ background-color: red; }";

#include <QProgressBar>

class MyProgressBar : public QProgressBar
{
public:
    MyProgressBar();
    void    setValue(int value);
};

void MyProgressBar::setValue(int value)
{
    if(value >= 0 && value < 60)
        this->setStyleSheet(style_0_60);
    else if (value >= 60 && value < 80)
        this->setStyleSheet(style_60_80);
    else
        this->setStyleSheet(style_80_100);

    QProgressBar::setValue(value);
}
c0vxltue

c0vxltue5#

我使用@三木的例子。它帮助了我很多,但它是纯色的。为了使它渐变,我修改了cpp。因为这是一个关于进度条中多种颜色的好线程,我认为这将是一个很好的贡献。

int val = value();
int pos = QStyle::sliderPositionFromValue(minimum(), maximum(), val, width());

QPainter p(this);

QLinearGradient linearGrad(this->rect().topLeft(), this->rect().bottomRight());
linearGrad.setColorAt(0, Qt::red);
linearGrad.setColorAt(0.2, QColor(255, 165, 0));
linearGrad.setColorAt(1, Qt::green);
QRect rect_linear(this->rect().topLeft(), this->rect().bottomRight());
p.fillRect(rect_linear, linearGrad);

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

uhry853o6#

我想可以先画整个渐变条。然后只画我们想要的部分。

代码,部分代码来自@三木,谢谢@Miki

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

    // Paint on pixmap
    QPixmap pixmap(w, h);
    QPainter pixmapPainter(&pixmap);
    QLinearGradient linearGradient(0, 0, w, h);
    linearGradient.setColorAt(0, Qt::green);
    linearGradient.setColorAt(0.5, Qt::yellow);
    linearGradient.setColorAt(1, Qt::red);

    QBrush pixmapBrush(linearGradient);
    pixmapPainter.setBrush(pixmapBrush);
    pixmapPainter.drawRect(0, 0, width(), height());

    // Paint the progress bar
    QPainter painter(this);
    QBrush brush(pixmap);
    painter.setBrush(brush);
    painter.drawRect(0, 0, pos, height());

    // Paint background
    painter.setPen(Qt::lightGray);
    painter.setBrush(QBrush(Qt::lightGray));
    painter.drawRect(pos, 0, width(), height());

    // Paint text
    painter.setPen(Qt::black);
    painter.setBrush(QBrush(Qt::black));
    painter.drawText(0, 0, width(), height(), Qt::AlignCenter, QString::number(val) + "%");
}
fbcarpbf

fbcarpbf7#

实际上,有一种简单的方法可以实现“Awin”答案中所示的效果,只需样式表。因此,您不需要创建自定义进度条类并覆盖paintEvent。但是,每次更改进度条值时,都需要使用setStyle更新样式。最好使用Qt的信号/插槽系统和来自进度条的valueChanged信号。
创建以下函数:

auto get_progress_bar_style(double fill_ratio) -> QString
{
    double x1 = 1. - fill_ratio;
    double x2 = x1 + 1.;

    QString style = "QProgressBar::chunk:horizontal{"
                    + "background: QLinearGradient(x1 : " 
                    + QString::number(x1)
                    + ", y1 : 0, x2 : " 
                    + QString::number(x2)
                    + ", y2 : 0, stop : 0 #009900, stop : 0.60 #DDDD00,"
                    + " stop : 0.75 #DDBB00, stop : 1 #DD0000);}";

    return style;
}

fill_ratio是当前值除以最大值。可以看到,该函数只调整线性渐变的x1x2值,并增加进度条的填充率。
由于我是Qt的新手,我不知道这种方法在性能方面有多“浪费”。编写一个自定义进度条类(如其他答案所示)可能更健壮,性能更好。然而,作为一个快速解决方案,演示的方法足以满足我的用例。

相关问题