Issue
I have an application which contains a QTableView
for which I would like to have the possibility to sort its contents but also to remove one or more rows. Below is an example code that implements this.
from PyQt5 import QtCore, QtWidgets
class NeXuSFilesModel(QtCore.QAbstractTableModel):
fields = ['col1','col2']
def __init__(self,parent):
super(NeXuSFilesModel,self).__init__(parent)
self._nexus_contents = [['aaa','111'],['bbb','222'],['ccc','333']]
def columnCount(self, parent=None):
return 2
def data(self,index,role):
if not index.isValid():
return QtCore.QVariant()
row = index.row()
col = index.column()
if role == QtCore.Qt.DisplayRole:
return str(self._nexus_contents[row][col])
else:
return QtCore.QVariant()
def headerData(self, index, orientation, role):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return NeXuSFilesModel.fields[index]
else:
return index + 1
return None
def removeRow(self, row, parent):
self.beginRemoveRows(QtCore.QModelIndex(),row,row+1)
del self._nexus_contents[row]
self.endRemoveRows()
return True
def rowCount(self, parent=None):
return len(self._nexus_contents)
class NeXuSDataTableView(QtWidgets.QTableView):
def __init__(self,parent):
super(NeXuSDataTableView,self).__init__(parent)
self.horizontalHeader().setStretchLastSection(True)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Delete:
model = self.model()
selected_indexes = self.selectionModel().selectedRows()
source_indexes_rows = sorted([model.mapToSource(index).row() for index in selected_indexes],reverse=True)
for row in source_indexes_rows:
model.sourceModel().removeRow(row,QtCore.QModelIndex())
super(NeXuSDataTableView, self).keyPressEvent(event)
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow,self).__init__()
self._table = NeXuSDataTableView(self)
model = NeXuSFilesModel(self)
proxy_model = QtCore.QSortFilterProxyModel()
proxy_model.setSourceModel(model)
self._table.setModel(proxy_model)
self._table.setSortingEnabled(True)
mainLayout = QtWidgets.QVBoxLayout()
mainLayout.addWidget(self._table)
self.setLayout(mainLayout)
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
_ = MainWindow()
app.exec_()
When I run that code, I fall into several problems for which I could not find the solution or could not understand the explanations given by the various sources I could find.
- When the program starts, the data is showed initially in the wrong order. Indeed, it is displayed in descending order whereas I would like to display it in ascending order
- When I remove one item, it removes actually two items !
Would you have any idea about what is wrong with my implementation ?
Solution
About both your questions:
- proxy_model.sort(0, QtCore.Qt.AscendingOrder) after self._table.sortSortingEnabled(True) results in an ascending order:
self._table.setSortingEnabled(True)
proxy_model.sort(0, QtCore.Qt.AscendingOrder)
mainLayout = QtWidgets.QVBoxLayout()
mainLayout.addWidget(self._table)
self.setLayout(mainLayout)
self.show()
- Using
self.beginRemoveRows(QtCore.QModelIndex(),row,row)
will remove only one row.
Answered By - Flow
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.