Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to update progress bar in delegate?



  • I have a TreeViewDelegate that is derived from QStyledItemDelegate. In this view, in a specific row and column I have a progress bar that now appears but, I'm not clear on how to update the progress bar from outside the delegate.

    Can anyone offer some advice?

    void MyTreeViewDelegate::paint(QPainter *painter,
        const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QModelIndex parent = index.parent();
    
        if (parent.row() < 0) {
            if (index.column() == 1 && index.row() == 1) {
                QStyleOptionProgressBar progressBarOption;
                progressBarOption.state = QStyle::State_Enabled;
                progressBarOption.direction = QApplication::layoutDirection();
                progressBarOption.rect = option.rect;
                progressBarOption.fontMetrics = QApplication::fontMetrics();
                progressBarOption.minimum = 0;
                progressBarOption.maximum = 100;
                progressBarOption.textAlignment = Qt::AlignCenter;
                progressBarOption.textVisible = true;
    
                bool is_number;
    
                int progress = index.data(Qt::DisplayRole).toInt(&is_number);
    
                if (is_number)
                    progressBarOption.progress = progress < 0 ? 0 : progress;
    
                progressBarOption.text = QString::asprintf("%d%% Complete",
                    progressBarOption.progress);
    
                QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                    &progressBarOption, painter);
            }
        }
    
        QStyledItemDelegate::paint(painter, option, index);
    
        return;
    }

  • Lifetime Qt Champion

    Hi,

    If you properly call dataChanged when modifying your model content, your progress bars should be updated automatically.



  • I guess I'm not clear on how that works. I now have the following ...

    void MyTreeViewDelegate::paint(QPainter *painter,
        const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QModelIndex parent = index.parent();
    
        if (parent.row() < 0) {
            if (index.column() == 1 && index.row() == 1) {
                QStyleOptionProgressBar progressBarOption;
                progressBarOption.state = QStyle::State_Enabled;
                progressBarOption.direction = QApplication::layoutDirection();
                progressBarOption.rect = option.rect;
                progressBarOption.fontMetrics = QApplication::fontMetrics();
                progressBarOption.minimum = 0;
                progressBarOption.maximum = 100;
                progressBarOption.textAlignment = Qt::AlignCenter;
                progressBarOption.textVisible = true;
    
                int progress = cars_processed;
    
                progressBarOption.progress = progress < 0 ? 0 : progress;
    
                progressBarOption.text = QString::asprintf("%d%% Complete",
                    progressBarOption.progress);
    
                QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                    &progressBarOption, painter);
            }
        }
    
        QStyledItemDelegate::paint(painter, option, index);
    
        return;
    }
    

    And say I have 100 cars. So in my MainWindow I have this ...

    for (auto& car : cars) {
        ++cars_processed;
    }
    

    As I increment the number of cars_processed, how do I immediately tell the paint function above to update the progress bar?


  • Lifetime Qt Champion

    As already suggested: you have to update your model content and ensure that dataChanged is called.

    Then, if you are updating your model in a tight loop, you might now see updates on your GUI because you are blocking the event loop.


Log in to reply