How to sort a QTableWidget with my own code?

2019-04-08 08:03发布

问题:

I am using Qt4.5.2 on Linux. I have a simple QTableWidget, in which a column displays dates in a human-friendly format. Unfortunately "human-friendly dates" are not easy to sort correctly. So, in the QTableWidget I keep a hidden column with the UNIX timestamp corresponding to that date.

I am trying to make sure that, whenever a request to sort on the DATE column is issued, in reality the sort be done on the (invisible) TIMESTAMP column. I tried reimplementing sortByColumn (this is in Python) by subclassing from QTableWidget and defining:

   def sortByColumn(self, col, order):
       print 'got request to sort col %d in order %s' % (col, str(order) )

Yet, whenever I click on one of the headers of my table the normal sort method continues to be called.

How can I override it?

回答1:

You could derive your own class of QTableWidgetItem and then write your own __lt__ operator. This would alleviate the need for an extra column as well. Something along the lines of:

from PyQt4 import QtCore, QtGui
import sys
import datetime

class MyTableWidgetItem(QtGui.QTableWidgetItem):
    def __init__(self, text, sortKey):
        #call custom constructor with UserType item type
        QtGui.QTableWidgetItem.__init__(self, text, QtGui.QTableWidgetItem.UserType)
        self.sortKey = sortKey

    #Qt uses a simple < check for sorting items, override this to use the sortKey
    def __lt__(self, other):
        return self.sortKey < other.sortKey

app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
window.setGeometry(0, 0, 400, 400)

table = QtGui.QTableWidget(window)
table.setGeometry(0, 0, 400, 400)
table.setRowCount(3)
table.setColumnCount(1)

date1 = datetime.date.today()
date2 = datetime.date.today() + datetime.timedelta(days=1)
date3 = datetime.date.today() + datetime.timedelta(days=2)

item1 = MyTableWidgetItem(str(date1.strftime("%A %d. %B %Y")), str(date1))
item2 = MyTableWidgetItem(str(date2.strftime("%A %d. %B %Y")), str(date2))
item3 = MyTableWidgetItem(str(date3.strftime("%A %d. %B %Y")), str(date3))

table.setItem(0, 0, item1)
table.setItem(2, 0, item2)
table.setItem(1, 0, item3)
table.setSortingEnabled(True)

window.show()
sys.exit(app.exec_())

This produced correct results for me, you can run it yourself to verify. The cell text displays text like "Saturday 20. February 2010" but when you sort on the column it will correctly sort by the sortKey field which is "2010-02-20" (iso formatted).

Oh, it should also be noted that this will NOT work with PySide because it appears that the __lt__ operator is not bound, where-as it is with PyQt4. I spent a while trying to debug why it wasn't working and then I switched from PySide to PyQt4 and it worked fine. You may notice that the __lt__ is not listed here:

http://www.pyside.org/docs/pyside/PySide/QtGui/QTableWidgetItem.html

but it is here:

http://doc.qt.digia.com/4.5/qtablewidgetitem.html#operator-lt