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.

Qt Code:
  1. #include <QApplication>
  2. #include <QStyledItemDelegate>
  3. #include <QPainter>
  4. #include <QTableView>
  5. #include <QStandardItemModel>
  6. #include <QHeaderView>
  7. #include <QPushButton>
  8. #include <QVBoxLayout>
  9. #include <QProxyStyle>
  10.  
  11. class ProgressBarStyle : public QProxyStyle
  12. {
  13. public:
  14. ProgressBarStyle(QStyle *style = nullptr) : QProxyStyle(style) {
  15. qDebug() << "ProgressBarStyle constructor called";
  16. }
  17.  
  18. void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override
  19. {
  20. if (element == CE_ProgressBar)
  21. {
  22. const QStyleOptionProgressBar *progressBarOption = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
  23. if (progressBarOption && progressBarOption->progress > 50)
  24. {
  25. QStyleOptionProgressBar progressBarOptionCopy(*progressBarOption);
  26. progressBarOptionCopy.palette.setColor(QPalette::Highlight, Qt::red);
  27.  
  28. QProxyStyle::drawControl(element, &progressBarOptionCopy, painter, widget);
  29. return;
  30. }
  31. }
  32.  
  33. QProxyStyle::drawControl(element, option, painter, widget);
  34. }
  35. };
  36.  
  37. class ProgressBarDelegate : public QStyledItemDelegate
  38. {
  39. public:
  40. ProgressBarDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
  41.  
  42. void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
  43. {
  44. int progress = index.data().toInt();
  45. QStyleOptionProgressBar progressBarOption;
  46. progressBarOption.rect = option.rect;
  47. progressBarOption.minimum = 0;
  48. progressBarOption.maximum = 100;
  49. progressBarOption.progress = progress;
  50. progressBarOption.text = QString::number(progress) + "%";
  51. progressBarOption.textVisible = true;
  52.  
  53. QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
  54. }
  55. };
  56.  
  57. int main(int argc, char *argv[])
  58. {
  59. QApplication app(argc, argv);
  60. QWidget window;
  61. QVBoxLayout layout(&window);
  62. QTableView tableView;
  63. layout.addWidget(&tableView);
  64. QPushButton button("Update Progress");
  65. layout.addWidget(&button);
  66. QStandardItemModel model(5, 3); // 5 rows and 3 columns
  67. tableView.setModel(&model);
  68.  
  69. // Set up data
  70. for (int row = 0; row < model.rowCount(); ++row) {
  71. for (int col = 0; col < model.columnCount(); ++col) {
  72. model.setData(model.index(row, col), (row + col) * 2);
  73. }
  74. }
  75.  
  76. // Set up delegate
  77. ProgressBarDelegate delegate;
  78. tableView.setItemDelegate(&delegate);
  79.  
  80. // Set up style
  81. ProgressBarStyle *style = new ProgressBarStyle;
  82. tableView.setStyle(style);
  83. app.setStyle(style);
  84.  
  85. // Connect button to update progress
  86. QObject::connect(&button, &QPushButton::clicked, [&model, &tableView]() {
  87. for (int row = 0; row < model.rowCount(); ++row) {
  88. for (int col = 0; col < model.columnCount(); ++col) {
  89. int progress = model.data(model.index(row, col)).toInt();
  90. progress = (progress + 10) % 110;
  91. model.setData(model.index(row, col), progress);
  92. }
  93. }
  94. tableView.viewport()->update();
  95. });
  96.  
  97. tableView.horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
  98. window.show();
  99. return app.exec();
  100. }
To copy to clipboard, switch view to plain text mode 

Any advise please? I am using Qt 6.5.0