如何更改QProgressBar的状态?

时间:2018-04-16 22:34:29

标签: c++ windows qt qt4 qt5

我有一个自定义对话框,它模仿和修饰QProgressDialog一些额外的特定于应用程序的信息,并允许暂停/恢复在后台运行的工作线程。最终我正在寻找的是能够改变QProgressBar的外观以反映this question中描述的暂停状态。

pause progress

奇怪的是,QWinTaskbarProgress似乎支持Qt 5.2的这个确切功能,但是在Qt4或Qt5中没有普通的QProgressBar。我可以在Qt源代码中摆弄,但是我已经在Qt源代码中挖掘了一下,我无法弄清楚查询/提供表单控件的实际状态,所以我无法弄清楚我需要改变什么。也许它不存在,因为这完全是Windows的事情,但也许不是吗?

使用CSS覆盖StyleSheet as recommended in the docs(以及here)会产生一个非常难看的进度条,与Windows 7进度条的存在完全不同。

正常:

normal appearance

样式表:

stylesheet appearance

我不想使用此选项。

1 个答案:

答案 0 :(得分:3)

简单的方法是将QGraphicsColorizeEffect设置为进度条。

像这样:

QProgressBar* progress = new QProgressBar;
progress->setGraphicsEffect(new QGraphicsColorizeEffect);

Win7上的结果:

enter image description here

嗯...结果看起来很好,但我们可以做得更好,只改变块颜色。

以下是最终结果:

enter image description here

重新实施QGraphicsEffect::draw到特定&自定义colourize效果区域:

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上的完整来源。

BTW,推荐Qt source code