我需要我的QProgressBar来更改特定值的颜色,例如
QProgressBar
但是我找不到解决办法。从样式表中,进度条的整个颜色会根据值而改变,但不会部分改变。我使用基于QT 5.4.1的QT creator 3.4.0。
QT 5.4.1
QT creator 3.4.0
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
为了完整起见,这里是自定义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(); }
我重复一遍,这只是一个简单的实现,看起来不太好,缺少一些用户可设置的功能,但可以作为一个起点。请随意编辑此代码。
sshcrbum2#
我发现了一个可以使用样式表的解决方案,尽管它不是很灵活。你可以设置QProgressBar的背景而不是块,然后使用反转的外观:
QProgressBar.setInvertedAppearance(True)
上面的命令是针对PyQt 5的,所以看看c++的正确命令。使用下面的样式表,我使用的渐变是垂直进度条,所以需要一些调整来使其水平正确。在这种情况下,也使用width:而不是height:。
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的麻烦!
yqkkidmi3#
你不能用现有的样式表属性来实现你想要的效果,但是你可以子类化QProgressBar并重新实现paint来获得你想要的外观。
gmol16394#
正如@Gabriel de Grimouard已经提到的,您需要对QProgressBar进行子类化并重新实现paint,但是还有另一种方法(可能有点脏,但是很快)--对QProgressBar进行子类化并修改setValue slot。
setValue
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); }
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());
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) + "%"); }
fbcarpbf7#
实际上,有一种简单的方法可以实现“Awin”答案中所示的效果,只需样式表。因此,您不需要创建自定义进度条类并覆盖paintEvent。但是,每次更改进度条值时,都需要使用setStyle更新样式。最好使用Qt的信号/插槽系统和来自进度条的valueChanged信号。创建以下函数:
setStyle
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是当前值除以最大值。可以看到,该函数只调整线性渐变的x1和x2值,并增加进度条的填充率。由于我是Qt的新手,我不知道这种方法在性能方面有多“浪费”。编写一个自定义进度条类(如其他答案所示)可能更健壮,性能更好。然而,作为一个快速解决方案,演示的方法足以满足我的用例。
fill_ratio
x1
x2
7条答案
按热度按时间smtd7mpg1#
你可以这样使用样式表:
它看起来像这样:
你可以简单地使用这个来使它更平滑:
更新:
这个解决方案是不正确的,因为如果值小于最大值,你会得到这样的结果:
正如其他人和这里所指出的:Gradient for chunks in QProgressBar
唯一的解决方案似乎是自定义
paintEvent
更新二:
为了完整起见,这里是自定义paintEvent的相关代码。这将工作,但看起来不是很好。此外,大多数参数应该是类成员并由用户设置。然而:
彩色进度条.h
coloredprogressbar.cpp
用法
我重复一遍,这只是一个简单的实现,看起来不太好,缺少一些用户可设置的功能,但可以作为一个起点。请随意编辑此代码。
sshcrbum2#
我发现了一个可以使用样式表的解决方案,尽管它不是很灵活。你可以设置QProgressBar的背景而不是块,然后使用反转的外观:
上面的命令是针对PyQt 5的,所以看看c++的正确命令。使用下面的样式表,我使用的渐变是垂直进度条,所以需要一些调整来使其水平正确。在这种情况下,也使用
width:
而不是height:
。这样做的一个限制是你不能使用带边距的块,而且你必须反转你为进度设置的值。所以100变成0,70变成30,等等。
你可以通过设置块的高度为0.5px这样的小值来使用它作为一个连续的进度条。希望它可以节省一些人子类化QProgressBar和实现painter的麻烦!
yqkkidmi3#
你不能用现有的样式表属性来实现你想要的效果,但是你可以子类化QProgressBar并重新实现paint来获得你想要的外观。
gmol16394#
正如@Gabriel de Grimouard已经提到的,您需要对
QProgressBar
进行子类化并重新实现paint,但是还有另一种方法(可能有点脏,但是很快)--对QProgressBar
进行子类化并修改setValue
slot。c0vxltue5#
我使用@三木的例子。它帮助了我很多,但它是纯色的。为了使它渐变,我修改了cpp。因为这是一个关于进度条中多种颜色的好线程,我认为这将是一个很好的贡献。
uhry853o6#
我想可以先画整个渐变条。然后只画我们想要的部分。
代码,部分代码来自@三木,谢谢@Miki
fbcarpbf7#
实际上,有一种简单的方法可以实现“Awin”答案中所示的效果,只需样式表。因此,您不需要创建自定义进度条类并覆盖
paintEvent
。但是,每次更改进度条值时,都需要使用setStyle
更新样式。最好使用Qt的信号/插槽系统和来自进度条的valueChanged
信号。创建以下函数:
fill_ratio
是当前值除以最大值。可以看到,该函数只调整线性渐变的x1
和x2
值,并增加进度条的填充率。由于我是Qt的新手,我不知道这种方法在性能方面有多“浪费”。编写一个自定义进度条类(如其他答案所示)可能更健壮,性能更好。然而,作为一个快速解决方案,演示的方法足以满足我的用例。