Qt QProgressBar not updating regularly when text is not visible

Question:

I have a QProgressBar that is set to not display text. It appears that this causes the progress bar to not update regularly, but only after some chunks (roughly 5-10%).

The following minimum Python example shows a window with two progress bars which get updated in sync. The one not displaying text is lagging behind.

Example

#!/usr/bin/env python3

from PyQt5 import QtCore, QtWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        layout = QtWidgets.QVBoxLayout(self)
        self.progressBar1 = QtWidgets.QProgressBar()
        self.progressBar2 = QtWidgets.QProgressBar()
        layout.addWidget(self.progressBar1)
        layout.addWidget(self.progressBar2)
        self.progressBar1.setTextVisible(False)
        self.progress = 0
        QtCore.QTimer.singleShot(1000, self.updateProgress)

    def updateProgress(self):
        self.progress = (self.progress+1) % 100
        self.progressBar1.setValue(self.progress)
        self.progressBar2.setValue(self.progress)
        QtCore.QTimer.singleShot(1000, self.updateProgress)

app = QtWidgets.QApplication([])
win = Window()
win.show()
app.exec()

Is this a bug?
Everything I could find about QProgressBar not updating correctly was about the main thread being stuck and not processing events, which doesn’t seem to be the case here.

The same behavior occurs in Python (PyQt5) and C++ (Qt 5.15.2, Qt 6.4.1)

Asked By: Andre

||

Answers:

It’s because the indicator bar of the progress bar is updated in chunks. See the QStyle::PM_ProgressBarChunkWidth in the reference.(See the implementation if you are interested.)

You can either change the style property or call repaint() manually, like these.

...
class Window(QtWidgets.QWidget):
    def __init__(self):
        ...
        self.progressBar1.setStyleSheet('QProgressBar::chunk {width: 1px;}')
        ...
...
class Window(QtWidgets.QWidget):
    def updateProgress(self):
        ...
        self.progressBar1.repaint()
        ...
Answered By: relent95
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.