Paul_Inkenbrandt | 2020-10-10 16:43:49 UTC | #1
I am creating an app with three different tableviews that are on three tabs. All three tables have a "join" field that could be used to connect them. I brought in the tables from pandas using the very useful tutorial on the subject (https://www.pythonguis.com/courses/model-views/qtableview-modelviews-numpy-pandas/). I want my script to automatically select rows in the other tables (based on the common field) if I select a row in the third table.
How would I programmatically select multiple rows given their indices? I want to select rows from one table automatically when I select rows from the other table.
Here is a link to my repository for those who are curious: https://github.com/inkenbrandt/wqxsde
Here is my best attempt to do what I am asking about, but it only appears to select one row in the other table, and not all the rows with a matching field:
def stationsel(self,s):
self.stationselection = self.StationTableView.selectionModel()
indexes = self.stationselection.selectedRows(column=2)
df = self.ResultModel._data
role = Qt.DisplayRole
dg = df[df['monitoringlocationid'].isin([self.StationModel.data(i, role) for i in indexes])]
print(dg)
mode = QItemSelectionModel.Select | QtCore.QItemSelectionModel.Rows
for i in dg.index:
self.ResultTableView.selectRow(i)
#for i in dg.index:
# self.ResultTableView.selectRow(i)
This is the closest thing I can find in Stack Exchange: https://stackoverflow.com/questions/9678138/how-to-select-next-row-in-qtableview-programmatically/9678278
Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!
martin | 2020-10-11 15:56:46 UTC | #2
Hey @Paul_Inkenbrandt I think you're very close here.
The .selectRow()
method on the view is a convenience method for single selection. For selecting multiple rows it looks as though you need to do this via the view's selection model. You've already got the selection model in self.stationselection
here, so it should be fairly straightforward.
QSelectionModel
has two .select()
methods -- one which takes individual QModelIndex
objects (single selection) and another that accepts a QItemSelection.
A QItemSelection is basically a list of selection ranges, see QItemSelectionRange
You can either build QItemSelectionRange
objects, or use the simpler method of passing a top left and bottom right QModelIndex
to QItemSelection.select(topLeft, bottomRight)
. Each additional call adds a new selection.
If you have non-contiguous selection blocks, what I think you're looking for is something like the following (code untested) --
def stationsel(self,s):
self.stationselection = self.StationTableView.selectionModel()
indexes = self.stationselection.selectedRows(column=2)
df = self.ResultModel._data
role = Qt.DisplayRole
dg = df[df['monitoringlocationid'].isin([self.StationModel.data(i, role) for i in indexes])]
model = self.StationTableView.model() # get data model for indexes.
selection = QItemSelection()
for i in dg.index:
# Get the model index for selection.
# Column shouldn't matter for row-wise.
model_index = model.index(i, 0)
# Select single row.
selection.select(model_index, model_index) # top left, bottom right identical
mode = QItemSelectionModel.Select | QtCore.QItemSelectionModel.Rows
# Apply the selection, using the row-wise mode.
self.stationselection.select(selection, mode)
If that doesn't do it let me know and I'll put together a complete example.
Paul_Inkenbrandt | 2020-10-11 16:04:07 UTC | #3
That worked! Thanks Martin! Here is my revised code.
pythondef stationsel(self,s): self.stationselection = self.StationTableView.selectionModel() indexes = self.stationselection.selectedRows(column=2) df = self.ResultModel._data role = Qt.DisplayRole dg = df[df['monitoringlocationid'].isin([self.StationModel.data(i, role) for i in indexes])] print(dg) model = self.ResultTableView.model() # get data model for indexes. selection = QItemSelection() for i in dg.index: self.ResultTableView.selectRow(i) model_index = model.index(i, 0) # Select single row. selection.select(model_index, model_index) # top left, bottom right identical mode = QItemSelectionModel.Select | QtCore.QItemSelectionModel.Rows # Apply the selection, using the row-wise mode. self.resultselection = self.ResultTableView.selectionModel() self.resultselection.select(selection, mode)
By the way, thank you for providing these resources. I bought the book and access to the videos, and I love it. The best resource for pyqt5 that I can find.
PyQt/PySide 1:1 Coaching with Martin Fitzpatrick — Get one on one help with your Python GUI projects. Working together with you I'll identify issues and suggest fixes, from bugs and usability to architecture and maintainability.