PDA

View Full Version : Cannot make my progressbar change of color with specific progress value



franco.amato
12th May 2023, 00:00
I wanted to try to render QProgressBar widgets inside cells of a table and I wanted the progress bars to change color if the progress value was, for example, greater than 50 (to represent a warning). To test it I created a very small project using a QTableView, a QStandardItemModel and a QProgressBar delegate to render a single table cell.

I tried different ways and none is working, the progress bar color is always green. Below the latest version of my code subclassing QProxyStyle.



#include <QApplication>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QTableView>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QPushButton>
#include <QVBoxLayout>
#include <QProxyStyle>

class ProgressBarStyle : public QProxyStyle
{
public:
ProgressBarStyle(QStyle *style = nullptr) : QProxyStyle(style) {
qDebug() << "ProgressBarStyle constructor called";
}

void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override
{
if (element == CE_ProgressBar)
{
const QStyleOptionProgressBar *progressBarOption = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
if (progressBarOption && progressBarOption->progress > 50)
{
QStyleOptionProgressBar progressBarOptionCopy(*progressBarOption);
progressBarOptionCopy.palette.setColor(QPalette::H ighlight, Qt::red);

QProxyStyle::drawControl(element, &progressBarOptionCopy, painter, widget);
return;
}
}

QProxyStyle::drawControl(element, option, painter, widget);
}
};

class ProgressBarDelegate : public QStyledItemDelegate
{
public:
ProgressBarDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
int progress = index.data().toInt();
QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect;
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textVisible = true;

QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
}
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
QVBoxLayout layout(&window);
QTableView tableView;
layout.addWidget(&tableView);
QPushButton button("Update Progress");
layout.addWidget(&button);
QStandardItemModel model(5, 3); // 5 rows and 3 columns
tableView.setModel(&model);

// Set up data
for (int row = 0; row < model.rowCount(); ++row) {
for (int col = 0; col < model.columnCount(); ++col) {
model.setData(model.index(row, col), (row + col) * 2);
}
}

// Set up delegate
ProgressBarDelegate delegate;
tableView.setItemDelegate(&delegate);

// Set up style
ProgressBarStyle *style = new ProgressBarStyle;
tableView.setStyle(style);
app.setStyle(style);

// Connect button to update progress
QObject::connect(&button, &QPushButton::clicked, [&model, &tableView]() {
for (int row = 0; row < model.rowCount(); ++row) {
for (int col = 0; col < model.columnCount(); ++col) {
int progress = model.data(model.index(row, col)).toInt();
progress = (progress + 10) % 110;
model.setData(model.index(row, col), progress);
}
}
tableView.viewport()->update();
});

tableView.horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
window.show();
return app.exec();
}

Any advise please? I am using Qt 6.5.0

Ginsengelf
12th May 2023, 07:18
Hi, have you tried CE_ProgressBarContents instead of using CE_ProgressBar?

I remember having similar problems in the past, and only getting it to work using a style sheet for background-color in QProgressBar::chunk.

Ginsengelf

franco.amato
12th May 2023, 08:15
Unfortunately changind to CE_ProgressBarContents didn't work

d_stranz
12th May 2023, 16:42
Maybe try a different color role instead of Highlight?