如何更改Qt中进度条默认样式的颜色

How to change color of default style for progressbar in Qt

如何在不更改其他默认渐变和效果的情况下更改默认 QProgressbar 样式中的绿色色调(有点明显的 "flow white chunk" 效果):

默认 QProgressbar 样式

.

我尝试使用 qlineargradientQProgressBar::chunk:horizo​​ntal 设置新的背景颜色组合,但我没有成功使用任何此类样式表保持提到的效果。

可能尝试像这样使用计时器更新样式表:

mRunner = 0.1;

QTimer *mTimer = new QTimer(this);
connect(mTimer, SIGNAL(timeout()), this, SLOT(updateProgress()));
mTimer->start(40);

并且方法应该为每个新步骤更改梯度:

void MainWindow::updateProgress()
{
    QString lStyle = QString("QProgressBar::chunk {background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:%1 white, stop:1 #b4b4b4);}").arg(mRunner);
    ui->progressBar->setStyleSheet(lStyle);

    mRunner += 0.01;
    if (mRunner > 1) {
        mRunner = 0.1;
    }
}

我也在做同样的事情。在改变块颜色的同时保持白色流动的块是困难的部分。白色流动的块也有它自己的条件。部分使用 Volodymyr 的例子,这就是我想出的

首先我们将 QProgressBar 子类化

ProgressBar.h

class AnimProgressBar : public QProgressBar
{
    Q_OBJECT

private:
    const double c_overtime = 0.25;
    const double c_speed    = 0.025;
    const double c_gsize    = 0.02;
    const double c_gap      = 0.1;
    const double opq        = 180;
    double overtime         = c_overtime;
    double speed            = c_speed;
    double gsize            = c_gsize;
    double gap              = c_gap;
    double aRunner          = -0.2;
    QString hue             = "120";
    QString val             = "170";
    const QString sat       = "255";

    std::mutex pbmtx;
    std::condition_variable pbcv;

    std::atomic<int> trueValue = 0;

    std::atomic_flag setFlag{};

public:
    QString font = "";
    AnimProgressBar(QWidget* parent = nullptr);

private:
    void valueUpdate();
    void commitValue(int value);

public slots:
    void ForeverLoop();
    void newValue(int value);
};

ProgressBar.cpp

AnimProgressBar::AnimProgressBar(QWidget * parent)
{
    QTimer *mTimer = new QTimer(this);
    connect(mTimer, SIGNAL(timeout()), this, SLOT(ForeverLoop()));
    mTimer->start(50);
}

然后我们设置颜色变化。在这种情况下,我使用的是 hsv。每个时钟周期1 + overtime是白色流动块的每个周期。时钟速度为 speed。以下是进度条流程中可能发生的所有场景

void AnimProgressBar::ForeverLoop()
{
    QString color = hue + ", " + sat + ", " + val;
    QString style
        = font + "QProgressBar::chunk {background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, ";
    QString trueopq = QString::number(255 - opq);
    double bRunner = aRunner + gsize;
    double aGap    = aRunner - gap;
    double bGap    = bRunner + gap;

    const auto BigOrEqual = [](double a, double b) { return a > b || AreDoubleSame(a, b); };
    const auto SmallOrEqual = [](double a, double b) { return a < b || AreDoubleSame(a, b); };

    // Symbols below are used to illustrate the progress bar coordination as visual representation
    // [xx] : this is the opaque block
    // [    : left side of the opaque block (aRunner)
    // ]    : right side of the opaque block (bRunner)
    // xx   : size of the opaque block (gap)
    // ---- : this is the solid color section
    // |S|   : this is the start point
    // |E|   : this is the end point
    // <==  : this is the gradient gap

    // |S|----------<==[xx]==>--------|E|
    // Illustration above is visual for progress bar where the opaque block is flowing within the visible section

    // Note: Visible section only exists between start point and end point, meaning in between |S| and |E|

    if (SmallOrEqual(bGap, 0) || BigOrEqual(aGap, 1))
    {
        // <==[xx]==>--|S|---
        // --|E|---<==[xx]==>
        // block and gradient gap are outside of visible section

        style.append("stop:0 hsv(%1)), stop:1 hsv(%1)");
    }
    else if (BigOrEqual(aRunner, 1))
    {
        if (SmallOrEqual(aGap, 0))
        {
            // <=|S|=|E|[xx]
            // whole chunk only contains the gradient gap area

            double num   = 255 - std::fmin(255, std::fabs(aGap) / gap * opq);
            style.append("stop:0 hsv(%1, " + QString::number(num) + ")");
        }
        else
        {
            // --|S|----------<=|E|=[xx]==>
            // small gradient gap still within visible section

            style.append("stop:" + QString::number(1 - gap) + " hsv(%1)");
        }

        double num = 255 - std::fmin(255, (1 + gap - aRunner) / gap * opq);
        style.append(", stop:1 hsv(%1, " + QString::number(num) + ")");
    }
    else if (SmallOrEqual(bRunner, 0))
    {
        // <==[xx]=|S|=>----------
        // only the gradient part of the opaque block is within the visible section at the start

        double num = 255 - std::fmax(0, bGap / gap * opq);
        style.append("stop:0 hsv(%1, " + QString::number(num) + "), stop:" + QString::number(bGap)
                     + " hsv(%1)");
    }
    else if (SmallOrEqual(aRunner, 0))
    {
        // <==[x|S|x]==>
        // only part of the opaque block is within the visible section at the start

        style.append("stop:0 hsv(%1, " + trueopq + ")");

        if (SmallOrEqual(bRunner, 1))
        {
            style.append(", stop:" + QString::number(bRunner) + " hsv(%1, " + trueopq + ")");

            if (BigOrEqual(bGap, 1))
            {
                // <==[x|S|x]==|E|>
                // the progress bar's chunk is small that right end of the gradient gap is hitting the end of the progress bar chunk

                double num   = 255 - std::fmin(255, bGap - 1 / gap * opq);
                style.append(", stop:1 hsv(%1, " + QString::number(num) + ")");
            }
            else
            {
                // <==[x|S|x]==>---------|E|
                //          ^
                //       bRunner
                // the progress bar's chunk gradient gap not hitting the end

                style.append(", stop:" + QString::number(bGap) + " hsv(%1)");
            }
        }
        else
        {
            // <==[x|S|x|E|]==>
            // the progress bar's chunk is so small that fits within the whole block
        }
    }
    else if (SmallOrEqual(aGap, 0))
    {
        // <=|S|=[xx]
        // part of the left gradient is outside of the start point

        double anum = 255 - std::fmin(255, std::fabs(aGap) / gap * opq);
        style.append("stop:0 hsv(%1, " + QString::number(anum) + "), stop:" + QString::number(aRunner) + " hsv(%1, " + trueopq + ")");

        if (SmallOrEqual(bRunner, 1))
        {
            style.append(", stop:" + QString::number(bRunner) + " hsv(%1, " + trueopq + ")");

            if (BigOrEqual(bGap, 1))
            {
                // <=|S|=[xx]=|E|=>
                // the part of the gradient area at left and right are outside of the start point and end point respectively

                double bextra = bGap - 1;
                double num    = 255 - std::fmin(255, gap + bextra / gap * opq);
                style.append(", stop:1 hsv(%1, " + QString::number(num) + ")");
            }
            else
            {
                // <=|S|=[xx]==>-------|E|
                // part of the left gradient is outside of the start point

                style.append(", stop:" + QString::number(bGap) + " hsv(%1)");
            }
        }
        else
        {
            // <=|S|=[x|E|x]==>
            // the part of the gradient area at left is outside of the start point while the block is outside of the end point
        }
    }
    else if (BigOrEqual(bRunner, 1))
    {
        // ------<==[x|E|x]==>
        // only part of the opaque block is within the end point

        style.append("stop:" + QString::number(aGap) + " hsv(%1), stop:" + QString::number(aRunner) + " hsv(%1, "
                     + trueopq + "), stop:0.99995 hsv(%1, " + trueopq + "), stop:1 hsv(%1)");
    }
    else if (BigOrEqual(bGap, 1))
    {
        // ------<==[xx]=|E|=>
        // part of the right gradient is outside of the end point

        double bextra   = bGap - 1;
        double bnum     = 255 - std::fmin(255, gap + bextra / gap * opq);
        style.append("stop:" + QString::number(aGap) + " hsv(%1), stop:" + QString::number(aRunner)
                     + " hsv(%1, " + trueopq + "), stop:" + QString::number(bRunner) + " hsv(%1, " + trueopq
                     + "), stop:1 hsv(%1, " + QString::number(bnum) + ")");
    }
    else
    {
        // |S|----------<==[xx]==>--------|E|
        // the opaque block is flowing within the visible section

        style.append("stop:" + QString::number(aGap) + " hsv(%1), stop:" + QString::number(aRunner)
                     + " hsv(%1, " + trueopq + "), stop:" + QString::number(bRunner) + " hsv(%1, " + trueopq
                     + "), stop:" + QString::number(bGap) + " hsv(%1)");
    }

    style.append(");}");

    setStyleSheet(style.arg(color));

    aRunner += speed;

    if (aRunner < 0 - overtime || aGap > 1 + overtime) aRunner = 0 - overtime;
}

对于值的每一次变化,我们都会修改 hsv、gap 和时钟速度

void AnimProgressBar::newValue(int value)
{
    int max = maximum();

    if (0 < value && value <= max)
    {
        double decivalue = value;
        double power     = decivalue / max;
        double mult      = max / std::min(max, value);
        overtime         = c_overtime * mult;
        speed            = c_spped * mult;
        gsize            = c_gsize * mult;
        gap              = c_gap * mult;
        hue              = QString::number(static_cast<int>(120 - (decivalue / max * 120)));
        val              = QString::number(static_cast<int>(170 + (decivalue / max* 55)));
    }

    if (value == max * 7 / 10) font = "QProgressBar { color: rgb(255, 255, 255); } ";

    setValue(value);
}

编辑:重写了更新循环