Как получить эффект цилиндра (2D) Progress Bar с помощью программирования Qt?

Как изменить цвет прогрессбара? Скажем, 40% для красного, 20% для зеленого, 40% для желтого и т. д. Я пытался использовать таблицы стилей, но обнаружил, что это работает только для плоских индикаторов выполнения, а не для 2D-баров.

введите здесь описание изображения


person Ques    schedule 21.07.2017    source источник
comment
пожалуйста, напишите, что вы уже сделали   -  person Nilabja    schedule 21.07.2017
comment
Сколько измерений будет иметь индикатор выполнения, если не 2?   -  person Nick    schedule 21.07.2017
comment
Вы пробовали что-то вроде разных тем Qt? Я думаю, что это зависит от конечного пользователя, как именно это будет выглядеть.   -  person flob    schedule 21.07.2017
comment
@NickA Кажется, его намерение - 2½D-презентация цилиндра. Не найдя клавишу [½] на своей клавиатуре, он пропустил ее в названии, что привело к путанице...   -  person Scheff's Cat    schedule 21.07.2017
comment
@Schefd имеет смысл, спасибо, что прояснили это   -  person Nick    schedule 21.07.2017
comment
ИМХО, в Qt есть несколько способов добиться этого: 1. Вы можете получить QProgressBar и перегрузите метод рисования. 2. Вы можете создать собственный QStyle где вы переопределяете рендеринг индикатора выполнения.   -  person Scheff's Cat    schedule 21.07.2017
comment
@Nilabja В настоящее время я использовал QPainter для создания индикатора выполнения с использованием фигур. Я не знаю, правильная ли это идея ... Но я могу нарисовать два эллипса и линии (расположенные горизонтально), что дает эффект цилиндра.   -  person Ques    schedule 25.07.2017


Ответы (1)


Чтобы иметь возможность создать этот эффект, мы рисуем эллипс, для этого мы могли бы помочь нам из QPainterPath придать ему форму, и мы поместили покрытие, которое является эллипсом, как показано ниже:

progressbar2d.h

#ifndef PROGRESSBAR2D_H
#define PROGRESSBAR2D_H

#include <QProgressBar>

class ProgressBar2D : public QProgressBar
{
    Q_OBJECT

public:
    ProgressBar2D(QWidget *parent = 0);
    ~ProgressBar2D();

protected:
    void paintEvent(QPaintEvent *);

private:
    void draw(QPainter *painter, QRect rect, int w);
    void drawEllipticalRectangle(QPainter *painter, QRect rect, int w);
};

#endif // PROGRESSBAR2D_H

progressbar2d.cpp

#include "progressbar2d.h"
#include <QPainter>

ProgressBar2D::ProgressBar2D(QWidget *parent): QProgressBar(parent)
{
}

ProgressBar2D::~ProgressBar2D()
{
}

void ProgressBar2D::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    int borde = height()/10;

    draw(&painter,
         QRect(borde, borde, width()-2*borde, height()-2*borde),
         2*borde);

    painter.drawText(rect(),  Qt::AlignCenter, QString("%1").arg(value()));

}

void ProgressBar2D::draw(QPainter *painter, QRect rect, int w)
{

    int w_percentage = 2*w + value()*(rect.width()-2*w)/maximum();

    painter->setBrush(QBrush(QColor("#81C253")));
    drawEllipticalRectangle(painter,
                            QRect(rect.topLeft(), QSize(w_percentage, rect.height()) ),
                            w);

    painter->setBrush(QBrush(QColor("#C3DDB1")));
    drawEllipticalRectangle(painter,
                            QRect(QPoint(rect.topLeft() + QPoint(w_percentage-2*w, 0)),
                                  QSize(rect.width()-w_percentage+2*w, rect.height()) ),
                            w);

    painter->setBrush(QBrush(QColor("#77896C")));
    painter->drawEllipse(QRect( rect.topLeft() + QPoint(rect.width()-2*w, 0) , QSize(2*w, rect.height())));

}


void ProgressBar2D::drawEllipticalRectangle(QPainter *painter, QRect rect, int w)
{
    painter->translate(rect.topLeft());

    QPainterPath path;

    path.moveTo(w, 0);
    path.arcTo(QRectF(0, 0, 2*w, rect.height()), 90, 180);
    path.lineTo(rect.width()-w, rect.height());

    path.arcTo(QRectF(rect.width()-2*w, 0, 2*w, rect.height()), 270, -180);
    path.lineTo(w, 0);
    painter->drawPath(path);

    painter->translate(-rect.topLeft());
}

main.cpp

#include "progressbar2d.h"
#include <QApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ProgressBar2D w;

    QTimer *timer = new QTimer(&w);

    QObject::connect(timer, &QTimer::timeout, [&w](){
        w.setValue((w.value()+1)%(1 + w.maximum()));
    });
    timer->start(100);
    w.show();

    return a.exec();
}

введите здесь описание изображения

person eyllanesc    schedule 25.07.2017
comment
Я могу сказать, что смотрю это уже две минуты подряд, это действительно гипнотизирует. Теперь мне нужны только цилиндрические индикаторы выполнения. - person Matteo Italia; 26.07.2017
comment
Я не понимаю. :П - person eyllanesc; 26.07.2017
comment
@eyllanesc: как изменить размер окна? setFixedSize здесь не работает - person Ques; 27.07.2017
comment
Какое окно, я не понимаю? - person eyllanesc; 27.07.2017
comment
@eyllanesc: я не понял эту строку в вашем коде, int w_percentage = 2*w + value()*(rect.width()-2*w)/maximum(), не могли бы вы рассказать мне об этом? - person Ques; 27.07.2017
comment
Какая линия? поясните лучше пожалуйста. - person eyllanesc; 27.07.2017
comment
Я имею в виду главное окно - person Ques; 27.07.2017
comment
Если вы понимаете, что покрытия представляют собой эллипсы высоты h и ширины w. - person eyllanesc; 27.07.2017
comment
В progressbar2d.cpp внутри draw() есть эта строка int w_percentage = 2*w + value()*(rect.width()-2*w)/maximum() - person Ques; 27.07.2017
comment
Если вы инкапсулируете цилиндр в прямоугольник, это прямоугольник, переданный функции рисования, а ширина эллипсов на боковых гранях равна w. - person eyllanesc; 27.07.2017
comment
Часть, которая показывает процент, должна закрасить часть цилиндра, и это расчет, чтобы узнать, какую часть закрасить, с небольшой геометрией, которую вы можете понять. - person eyllanesc; 27.07.2017