[PyQt] Animated Progress Bars in QTableView - how?
Dave Gradwell
davegradwell at yahoo.co.uk
Fri May 30 11:56:56 BST 2014
Hi List,
I have a QTableView in which I want to draw a column with progress bars.
I considered the Qt Torrent example application and re-implemented the paint function of the QStyledItemDelegate like this:
def paint(self, painter, option, index):
if index.column() == 1:
progressBar = QtGui.QStyleOptionProgressBarV2()
progressBar.state = QtGui.QStyle.State_Enabled
progressBar.direction = QtGui.QApplication.layoutDirection()
progressBar.rect = option.rect
progressBar.fontMetrics = QtGui.QApplication.fontMetrics()
progressBar.minimum = 0
progressBar.maximum = 100
progressBar.textAlignment = QtCore.Qt.AlignCenter
progressBar.textVisible = True
progressBar.progress = 20 # for testing
QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_ProgressBar, progressBar, painter)
return super(progressBarDelegate, self).paint(painter, option, index)
However, this gave me a column of greyed-out progress bars - with no animation.
http://www.bonhardapple.com/shared-with-others/delegated-style.png
This isn't what the screenshots in the docs portray of the example.
Then I found out about QTableView's setIndexWidget().
I tried to implement setIndexWidget() whenever data() was called on the model but no progress bars were shown.
So I thought I'd try setIndexWidget() in the delegate paint() code.
I created a dictionary (self.parent.progressBarPool) to track which progress bars had been manufactured - to avoid excessive creation/deletion I guess.
def paint(self, painter, option, index):
if index.column() == 1:
if not index.row() in self.parent.progressBarPool:
progressBar = QtGui.QProgressBar()
self.parent.progressBarPool[index.row()] = progressBar
progressBar.setMinimum(0)
# progressBar.setAutoFillBackground(True) # docs say this needs to be true, but you get a better row-highlight appearance with it False
self.parent.tableView.setIndexWidget(index, progressBar)
else:
progressBar = self.parent.progressBarPool[index.row()]
progressBar.setValue(20) # for testing
return super(progressBarDelegate, self).paint(painter, option, index)
This looked great...
http://www.bonhardapple.com/shared-with-others/first-glance.png
... however, when I scrolled, the progress bars didn't move in concert with the rest of the scroll area.
They floated above the cells which scrolled away underneath them.
http://www.bonhardapple.com/shared-with-others/scrolled.png
I've now hacked things a bit so that the self.parent.progressBarPool is deleted when there's a wheelEvent.
This causes a flickery redraw on (one type of) scroll but feels like a growing stack of hacks rather than a solution.
Accordingly, I would appreciate any advice on the right way to do this.
With thanks,
Dave.
pyqt 4.10.1
qt 4.8.4
Mac OS 10.6.8
Also posted this question on Stack Overflow:
http://stackoverflow.com/questions/23952858/animated-progress-bars-in-qtableview-how
More information about the PyQt
mailing list