我有一个模仿和修饰的自定义对话框 QProgressDialog一些额外的特定于应用程序的信息,并启用暂停/恢复在后台运行的工作线程。最终我要寻找的是改变 QProgressBar 外观的能力。以反射(reflect)暂停状态,如 this question 中所述.
奇怪的是QWinTaskbarProgress从 Qt 5.2 开始似乎支持这个确切的功能,但是一个普通的 QProgressBar不会,在 Qt4 或 Qt5 中。我可以在 Qt 源代码中摆弄,但我已经在 Qt 源代码中挖掘,我无法弄清楚表单控件的实际状态是在哪里查询/提供的,所以我无法弄清楚找出我需要改变的地方。也许它不存在,因为这完全是 Windows 的事情,但也许不是?
使用 CSS 覆盖样式表 as recommended in the docs (和 here )导致一个非常难看的进度条,在外观上与普通的 Windows 7 进度条完全不同。
正常:
样式表:
我不想使用这个选项。
最佳答案
简单的方法是设置QGraphicsColorizeEffect到进度条。
像这样:
QProgressBar* progress = new QProgressBar;
progress->setGraphicsEffect(new QGraphicsColorizeEffect);
Win7 上的结果:
嗯...结果看起来不错,但我们可以让它变得更好,只改变 block 的颜色。
最终结果如下:
重新实现 QGraphicsEffect::draw
以指定和自定义着色效果区域:
class Colorize : public QGraphicsEffect {
public:
explicit Colorize(QObject *parent = Q_NULLPTR) :
QGraphicsEffect(parent),
strength(1),
color(Qt::red),
effectRect()
{ }
quint32 strength;
QColor color;
QRectF effectRect;
protected:
void draw(QPainter* painter) {
QPoint offset;
const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset);
draw(painter, offset, pixmap, QRect());
}
void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const
{
if (src.isNull())
return;
QImage srcImage;
QImage destImage;
if (srcRect.isNull()) {
srcImage = src.toImage();
srcImage = srcImage.convertToFormat(srcImage.hasAlphaChannel() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
destImage = QImage(srcImage.size(), srcImage.format());
} else {
QRect rect = srcRect.toAlignedRect().intersected(src.rect());
srcImage = src.copy(rect).toImage();
srcImage = srcImage.convertToFormat(srcImage.hasAlphaChannel() ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
destImage = QImage(rect.size(), srcImage.format());
}
destImage.setDevicePixelRatio(src.devicePixelRatioF());
// do colorizing
QPainter destPainter(&destImage);
grayscale(srcImage, destImage, srcImage.rect());
destPainter.setCompositionMode(QPainter::CompositionMode_Screen);
destPainter.fillRect(effectRect, color);
destPainter.end();
// alpha blending srcImage and destImage
if(0 < strength && strength < 1){
QImage buffer = srcImage;
QPainter bufPainter(&buffer);
bufPainter.setOpacity(strength);
bufPainter.drawImage(0, 0, destImage);
bufPainter.end();
destImage = buffer;
}
if (srcImage.hasAlphaChannel())
destImage.setAlphaChannel(srcImage.alphaChannel());
painter->drawImage(dest, destImage);
}
};
计算进度条的grove rect:
QRectF getGrooveRect() const {
StyleOptionProgressBar option;
option.initFrom(this); // this ⇒ progress bar
return style()->subElementRect(QStyle::SE_ProgressBarGroove, &option, this);
}
...
class StyleOptionProgressBar : public QStyleOptionProgressBar {
public:
using QStyleOptionProgressBar::QStyleOptionProgressBar;
void initFrom(const ColorizeProgressBar* w) {
init(w);
minimum = w->minimum();
maximum = w->maximum();
progress = w->value();
text = w->text();
textAlignment = w->alignment();
textVisible = w->isTextVisible();
orientation = w->orientation();
invertedAppearance = w->invertedAppearance();
}
};
完整来源 Github .
顺便说一句,转介 Qt source code
关于c++ - 如何更改 QProgressBar 的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49867207/