Reputation: 8419
I have a QTableView
on which I override the keyPressEvent
method such as when the user presses the tab key on the lowest right corner, a new line is appended to the underlying (pandas) model. Once this is done I want the current index to be located at the new lowest right corner. Here is an example classed that should do in principle the job:
from PyQt5 import QtCore, QtWidgets
class DL50TableView(QtWidgets.QTableView):
def keyPressEvent(self, event):
key = event.key()
model = self.model()
current_index = self.currentIndex()
row = current_index.row()
column = current_index.column()
if key == QtCore.Qt.Key_Tab:
if column == model.columnCount() - 1 and row == model.rowCount() - 1:
model.insertRows(model.rowCount())
index = model.index(model.rowCount() - 1,model.columnCount() - 1)
self.setCurrentIndex(index)
elif key == QtCore.Qt.Key_Backspace:
if column == 0 and row == model.rowCount() - 1:
model.removeRows(model.rowCount() - 1)
index = model.index(model.rowCount() - 1,0)
self.setCurrentIndex(index)
super(DL50TableView, self).keyPressEvent(event)
import pandas as pd
from PyQt5 import QtCore, QtGui
class DL50Model(QtCore.QAbstractTableModel):
def __init__(self, *args, **kwargs):
super(DL50Model,self).__init__(*args, **kwargs)
self._data = pd.DataFrame([self.default_line()], columns=['include',
'dose',
'response',
'nominal',
'log10(dose)',
'contrib.\ndae',
'prob.\nof\nresponse',
'likelihood\ncontrib.',
'prob.\nof\nresponse\n(sub)',
'likelihood\ncontrib.\n(sub)',
'prob.\nof\nresponse\n(over)',
'likelihood\ncontrib.\n(over)'])
def columnCount(self, parent=None):
return len(self._data.columns)
def data(self, index, role):
if not index.isValid():
return False
row = index.row()
col = index.column()
if role == QtCore.Qt.BackgroundRole and col >= 3:
return QtGui.QBrush(QtCore.Qt.gray)
elif role == QtCore.Qt.CheckStateRole and col in [0,2,3]:
return self._data.iloc[row][col]
elif role == QtCore.Qt.DisplayRole:
if col in [0,2,3]:
return None
return str(self._data.iloc[row][col])
return None
def default_line(self):
return [False, 0.0,False, False, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
def insertRows(self, position, rows=1, index=QtCore.QModelIndex()):
"""Insert row(s) into the model.
Args:
position (int): the position of the row(s) to iunsert
rows (int): the number of rows to insert
index (QModelIndex): the parent index
"""
self.beginInsertRows(QtCore.QModelIndex(), position, position + rows - 1)
default = [self.default_line()]*rows
lines = pd.DataFrame(default, columns=self._data.columns)
self._data = pd.concat([self._data.iloc[:position], lines, self._data.iloc[position:]]).reset_index(drop=True)
self.endInsertRows()
return True
def removeRows(self, position, rows=1, parent=QtCore.QModelIndex()):
"""Remove row(s) from the model.
Args:
position (int): the position of the row(s) to delete
rows (int): the number of rows to delete
index (QModelIndex): the parent index
"""
self.beginRemoveRows(QtCore.QModelIndex(), position, position + rows - 1)
print('BEFORE', len(self._data.index))
self._data.drop(self._data.index[position:position+rows], inplace=True)
print('AFTER', len(self._data.index))
self.endRemoveRows()
return True
def rowCount(self, parent=None):
return len(self._data.index)
When running that code, a new line is actually appended when I press tab but the currentIndex
is set to (0,0)
instead of the lowest right corner as expected by the code I wrote. Would you know what is wrong with my view/model ?
Upvotes: 2
Views: 2078
Reputation: 243897
By overriding the keyPressEvent method since after implementing your custom logic you are invoking the default code that the tab uses to move the currentIndex, and since your currentIndex is in the bottonRight then it will move to the topLeft.
One possible solution is to prevent the default behavior from running using the "return" statement:
# ...
if key == QtCore.Qt.Key_Tab:
if column == model.columnCount() - 1 and row == model.rowCount() - 1:
model.insertRows(model.rowCount())
index = model.index(model.rowCount() - 1, model.columnCount() - 1)
self.setCurrentIndex(index)
return
# ...
Upvotes: 2