[PyQt] Selecting many rows in a QTableView

Thomas Robitaille thomas.robitaille at gmail.com
Mon Aug 8 23:26:47 BST 2016


Hi everyone,

I am trying to create a QTableView in Qt which is efficient for large
tables. I've managed to make the display of data efficient by defining
my own abstract table model:

```
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import Qt


class DataTableModel(QtCore.QAbstractTableModel):

    def columnCount(self, index=None):
        return 3

    def rowCount(self, index=None):
        return 10000

    def headerData(self, section, orientation, role):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return 'c'
        elif orientation == Qt.Vertical:
            return 'r'

    def data(self, index, role):
        if not index.isValid():
            return None
        if role == Qt.DisplayRole:
            return "({0},{1})".format(index.row(), index.column())

app = QtGui.QApplication([""])
viewer = QtGui.QTableView()
model = DataTableModel()
viewer.setModel(model)
viewer.show()
```

This works fine, because the data method is only called for cells that
appear in the field of view of the table.

I now want to display an existing selection of some fraction of the rows:

```
import numpy as np
selected_rows = np.where(np.random.random(10000) > 0.5)[0]
```

I can tell the table widget about this selection by doing e.g.:

```
smodel = viewer.selectionModel()
for row in selected_rows:
    model_index = model.createIndex(row, 0)
    smodel.select(model_index, QtGui.QItemSelectionModel.Select |
QtGui.QItemSelectionModel.Rows)
```

However, this is very inefficient. It typically takes a second to
select 1000-2000 rows, when in practice I have tables with millions of
rows. There may be ways of speeding up this loop, but I would like to
do away with the loop altogether, and instead have Qt only ask me
(similarly to the data itself) for information about selections within
the visible cells (similar to what happens with the data model). Is
this possible, and if so, what is the best way to achieve this?

I asked this question on StackOverflow [1] - the two solutions
suggested there are:

- Build up a QItemSelection and select rows at the last minute: this
is not a good solution in my case because it's still slow.

- Create a custom item selection model: this doesn't seem to work
because non-virtual methods such as isSelected can't be overridden.

Does anyone here have any other suggestions for how to achieve this?

Thanks,
Tom

[1] http://stackoverflow.com/questions/38829929/selecting-many-rows-in-qt-table


More information about the PyQt mailing list