Sorting In Pyqt Tablewidget
Solution 1:
Its sorting alpha-numerically (so, in terms of strings, '1', '10', '11', '12', '2', '20', '21', '22', '3', '4' etc. is the proper sort order. It appears that for a QTableWidgetItem, if you use the setData(Qt.EditRole, value) method, the sort order will work. Depending on your version of Qt (I assume) you may have to overload the less than method of your table widget item.
from PyQt4.QtCore import Qt, QVariant
from PyQt4.QtGui import QApplication, QTableWidget, QTableWidgetItem
class MyTableWidgetItem(QTableWidgetItem):
def __lt__(self, other):
if ( isinstance(other, QTableWidgetItem) ):
my_value, my_ok = self.data(Qt.EditRole).toInt()
other_value, other_ok = other.data(Qt.EditRole).toInt()
if ( my_ok and other_ok ):
return my_value < other_value
return super(MyTableWidgetItem, self).__lt__(other)
if ( __name__ == '__main__' ):
app = None
if ( QApplication.instance() is None ):
app = QApplication([])
widget = QTableWidget()
widget.setWindowFlags(Qt.Dialog)
widget.setSortingEnabled(True)
widget.setRowCount(50)
widget.setColumnCount(3)
for row in range(50):
# create a normal QTableWidgetItem
a = QTableWidgetItem()
a.setText(str(row))
widget.setItem(row, 0, a)
# create a proper sorted item
b = QTableWidgetItem()
b.setData(Qt.EditRole, QVariant(row))
widget.setItem(row, 1, b)
# create a custom sorted item
c = MyTableWidgetItem()
c.setData(Qt.EditRole, QVariant(row))
widget.setItem(row, 2, c)
widget.show()
if ( app ):
app.exec_()
Solution 2:
An alternative to using a custom Item
is to use a SortFilterProxy
(which you probably should be doing anyway). In that case you can define a lessThan
method that will be used for sorting. Here's mine:
classSortFilterProxyModel(QSortFilterProxyModel):
deflessThan(self, left_index, right_index):
left_var = left_index.data(Qt.EditRole)
right_var = right_index.data(Qt.EditRole)
try:
returnfloat(left_var) < float(right_var)
except (ValueError, TypeError):
passreturn left_var < right_var
It uses the EditRole
to get the data for sorting, so you can do whatever mapping for usability you want to do in the DisplayRole
cases. It also just tries to do numerical sorting for values than can be converted to float
, or native sorting otherwise. Not the most general approach, but seems to work well for me. YMMV.
Solution 3:
Another possible solution to sort numeric could be, to add a special attribute and compare it based on that value. Mybe that is a more java like way.
classMyTableWidgetItem(QTableWidgetItem):def__init__(self, value):
QTableWidgetItem.__init__(self)
self.value = value
def__lt__(self, other):
if isinstance(other, MyTableWidgetItem):
returnself.value < other.value
returnsuper(QTableWidgetItem, self).__lt__(other)
Solution 4:
A simpler way is to prepend a few blank spaces to your numeric text. The ascii value of ' ' is less than '0', so it will work as you want it to. Here is what I do:
element = str(num) # convert to str
padded = (' '+element)[-5:] # make all elements the same length
item.setText(padded)
Post a Comment for "Sorting In Pyqt Tablewidget"