Scrollbar jumping to top when shifting rows in QTableView
Unsolved
General and Desktop
-
The following program will intermittently enter a failure mode where the scrollbar jumps at the top whenever a new row is added (and the first one discarded). The failure mode is sometimes triggered by the main window losing and reacquiring focus. How do I fix this bug?
import sys from PyQt5 import QtCore, QtWidgets class _Scroller(QtCore.QAbstractTableModel): def __init__(self, parent): QtCore.QAbstractTableModel.__init__(self, parent) self.headers = ["Test"] self.depth = 20 self.entries = [] self.counter = 0 timer = QtCore.QTimer(self) timer.timeout.connect(self.timer_tick) timer.start(100) def headerData(self, col, orientation, role): if (orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole): return self.headers[col] return None def rowCount(self, parent): return len(self.entries) def columnCount(self, parent): return len(self.headers) def insertRows(self, position, rows=1, index=QtCore.QModelIndex()): self.beginInsertRows(QtCore.QModelIndex(), position, position+rows-1) self.endInsertRows() def removeRows(self, position, rows=1, index=QtCore.QModelIndex()): self.beginRemoveRows(QtCore.QModelIndex(), position, position+rows-1) self.endRemoveRows() def timer_tick(self): to_add = [self.counter] self.counter += 1 nrows = len(self.entries) self.entries.extend(to_add) self.insertRows(nrows, len(to_add)) if len(self.entries) > self.depth: start = len(self.entries) - self.depth self.entries = self.entries[start:] self.removeRows(0, start) def data(self, index, role): if index.isValid(): if role == QtCore.Qt.DisplayRole: return str(self.entries[index.row()]) def main(): app = QtWidgets.QApplication(sys.argv) w = QtWidgets.QMainWindow() table = QtWidgets.QTableView() w.setCentralWidget(table) w.show() table.setModel(_Scroller(table)) sys.exit(app.exec_()) if __name__ == '__main__': main()