排序 QTableView 时如何保留选择
how to preserve selection when sorting QTableView
如何在对 table 进行排序时保留项目的 selection?在下面的示例中,selection 始终固定到行索引,即如果我 select 第一行,那么在排序后总是第一行是 selected,而不是我拥有的实际行selected.
import sys
from PySide2 import QtWidgets, QtGui, QtCore
from PySide2.QtCore import Qt
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def data(self, index, role):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]
def sort(self, column, order):
if order == Qt.DescendingOrder:
rev = True
else:
rev = False
self.layoutAboutToBeChanged.emit()
self._data.sort(key=lambda x: x[column], reverse=rev)
self.layoutChanged.emit()
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0])
class Main(QtWidgets.QDialog):
def __init__(self, data):
super().__init__()
self.layout = QtWidgets.QVBoxLayout()
self.table = QtWidgets.QTableView()
self.table.setSortingEnabled(True)
self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.model = TableModel(data)
self.table.setModel(self.model)
self.layout.addWidget(self.table)
self.setLayout(self.layout)
def main():
app = QtWidgets.QApplication(sys.argv)
data = [
[1,2,3,4],
[5,6,7,8],
[6,5,4,3],
[2,1,0,9]
]
m = Main(data)
m.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
在实现排序方法时,您正在修改数据,并且视图无法知道项目的新位置,您必须使用 QSortFilterProxyModel 修改索引,而不是修改数据:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return self._data[index.row()][index.column()]
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0])
class Main(QtWidgets.QDialog):
def __init__(self, data):
super().__init__()
self.layout = QtWidgets.QVBoxLayout()
self.table = QtWidgets.QTableView()
self.table.setSortingEnabled(True)
self.table.setSelectionBehavior(
QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows
)
self.model = TableModel(data)
<b>self.proxy = QtCore.QSortFilterProxyModel()
self.proxy.setSourceModel(self.model)
self.table.setModel(self.proxy)</b>
self.layout.addWidget(self.table)
self.setLayout(self.layout)
def main():
app = QtWidgets.QApplication(sys.argv)
data = [[1, 2, 3, 4], [5, 6, 7, 8], [6, 5, 4, 3], [2, 1, 0, 9]]
m = Main(data)
m.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
如何在对 table 进行排序时保留项目的 selection?在下面的示例中,selection 始终固定到行索引,即如果我 select 第一行,那么在排序后总是第一行是 selected,而不是我拥有的实际行selected.
import sys
from PySide2 import QtWidgets, QtGui, QtCore
from PySide2.QtCore import Qt
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def data(self, index, role):
if role == Qt.DisplayRole:
return self._data[index.row()][index.column()]
def sort(self, column, order):
if order == Qt.DescendingOrder:
rev = True
else:
rev = False
self.layoutAboutToBeChanged.emit()
self._data.sort(key=lambda x: x[column], reverse=rev)
self.layoutChanged.emit()
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0])
class Main(QtWidgets.QDialog):
def __init__(self, data):
super().__init__()
self.layout = QtWidgets.QVBoxLayout()
self.table = QtWidgets.QTableView()
self.table.setSortingEnabled(True)
self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.model = TableModel(data)
self.table.setModel(self.model)
self.layout.addWidget(self.table)
self.setLayout(self.layout)
def main():
app = QtWidgets.QApplication(sys.argv)
data = [
[1,2,3,4],
[5,6,7,8],
[6,5,4,3],
[2,1,0,9]
]
m = Main(data)
m.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
在实现排序方法时,您正在修改数据,并且视图无法知道项目的新位置,您必须使用 QSortFilterProxyModel 修改索引,而不是修改数据:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return self._data[index.row()][index.column()]
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0])
class Main(QtWidgets.QDialog):
def __init__(self, data):
super().__init__()
self.layout = QtWidgets.QVBoxLayout()
self.table = QtWidgets.QTableView()
self.table.setSortingEnabled(True)
self.table.setSelectionBehavior(
QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows
)
self.model = TableModel(data)
<b>self.proxy = QtCore.QSortFilterProxyModel()
self.proxy.setSourceModel(self.model)
self.table.setModel(self.proxy)</b>
self.layout.addWidget(self.table)
self.setLayout(self.layout)
def main():
app = QtWidgets.QApplication(sys.argv)
data = [[1, 2, 3, 4], [5, 6, 7, 8], [6, 5, 4, 3], [2, 1, 0, 9]]
m = Main(data)
m.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()