I have a QStandardItemModel piped into a QTableView. One of the columns in my model contains dates which have user-friendly displayData and computer-friendly userData. So for example one QStandardItem might display a string like 22 Nov 2018
but the userdata would look like 324586
(seconds since the epoch). However when I sort the column it of course sorts by the displayData. How can I force the table to sort by userData instead?
Asked
Active
Viewed 2,556 times
1
1 Answers
4
You have to use setSortRole():
from PyQt5 import QtCore, QtGui, QtWidgets
import random
DATECOLUMN = 1
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self._tableView = QtWidgets.QTableView()
self.setCentralWidget(self._tableView)
self._model = QtGui.QStandardItemModel(10, 4)
self._tableView.setModel(self._model)
now_second = QtCore.QDateTime.currentDateTime().toSecsSinceEpoch()
for i in range(self._model.rowCount()):
for j in range(self._model.columnCount()):
if j == DATECOLUMN:
t = QtCore.QDateTime.fromSecsSinceEpoch(random.randint(0, now_second))
text = t.toString("dd MMM yyyy")
it = QtGui.QStandardItem(text)
it.setData(t.toSecsSinceEpoch(), QtCore.Qt.UserRole)
else:
it = QtGui.QStandardItem("{}-{}".format(i, j))
self._model.setItem(i, j, it)
self._model.setSortRole(QtCore.Qt.UserRole)
self._model.sort(DATECOLUMN, QtCore.Qt.AscendingOrder)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Although I prefer to save the QDateTime directly and use a delegate to show the data with the format you want.
from PyQt5 import QtCore, QtGui, QtWidgets
import random
DATECOLUMN = 1
class DateDelegate(QtWidgets.QStyledItemDelegate):
def displayText(self, value, locale):
return locale.toString(value, "dd MMM yyyy")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self._tableView = QtWidgets.QTableView()
self.setCentralWidget(self._tableView)
self._model = QtGui.QStandardItemModel(10, 4)
self._tableView.setModel(self._model)
delegate = DateDelegate(self._tableView)
self._tableView.setItemDelegateForColumn(DATECOLUMN, delegate)
now_second = QtCore.QDateTime.currentDateTime().toSecsSinceEpoch()
for i in range(self._model.rowCount()):
for j in range(self._model.columnCount()):
if j == DATECOLUMN:
t = QtCore.QDateTime.fromSecsSinceEpoch(random.randint(0, now_second))
it = QtGui.QStandardItem()
it.setData(t, QtCore.Qt.DisplayRole)
else:
it = QtGui.QStandardItem("{}-{}".format(i, j))
self._model.setItem(i, j, it)
self._model.sort(DATECOLUMN, QtCore.Qt.AscendingOrder)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

eyllanesc
- 235,170
- 19
- 170
- 241
-
Ah, so I need to set it on the model, not the view! Still getting used to where everything lives in model/view framework... Thanks for the very complete answer! – Spencer Nov 27 '18 at 02:42
-
@Spencer I recommend you read: http://doc.qt.io/qt-5/model-view-programming.html so you understand something about MVC in Qt. On the other hand I suggest that for future questions where you point out that something is failing you provide a [mcve] – eyllanesc Nov 27 '18 at 02:45