[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