Issue
How do I alter the column sorting behavior so that instead of sorting alphabetically like this:
1, 11.1, 2, 22.2, 3, etc.
it will sort numerically, like this:
1, 2, 3, 11.1, 22.2, etc
I need to alter the sorting behavior only on specific columns and not to the whole table, as I want to keep the normal alphabetic ordering for names.
I also have a column that has file sizes. They are represented in MB and GB, and I want to sort it so that 800 MB will come first and 1.4 GB will come after. It also has the problem of alphabetic sorting. Is there a method that can do this?
Solution
Probably the simplest and most flexible way to do this is to store the raw values (for sorting) alongside the formatted values (for display). You can then subclass QTableWidgetItem
and reimplement its less than operator, so that only the raw values are compared when sorting. This subclass can be used selectively for whichever columns need special sorting.
For this to work correctly with file sizes, you will need to store the raw values as byte-counts so that all formats can be compared in the same way.
Here's a simple demo that shows how to implement this:
import sys
from PyQt5 import QtCore, QtWidgets
class NumericItem(QtWidgets.QTableWidgetItem):
def __lt__(self, other):
return (self.data(QtCore.Qt.UserRole) <
other.data(QtCore.Qt.UserRole))
class Window(QtWidgets.QTableWidget):
def __init__(self):
super(Window, self).__init__(6, 3)
for column, values in enumerate((
('Red', 'Green', 'Yellow', 'Blue', 'White', 'Black'),
(1, 11.1, 2, 22.2, 3, 17),
(37885792, 755, 25504, 4805, 3751225472, 14529792),
)):
for row, value in enumerate(values):
if column == 0:
item = QtWidgets.QTableWidgetItem(value)
else:
if column == 1:
text = str(value)
else:
text = self.formatSize(value)
item = NumericItem(text)
item.setData(QtCore.Qt.UserRole, value)
self.setItem(row, column, item)
self.setSortingEnabled(True)
self.sortItems(0, QtCore.Qt.AscendingOrder)
def formatSize(self, size, precision=2):
if size < 0:
return ''
if size < 1024:
return '%.0f B' % size
size /= 1024.0
if size < 1024:
return '%.*f KiB' % (precision, size)
size /= 1024
if size < 1024:
return '%.*f MiB' % (precision, size)
return '%.*f GiB' % (precision, size / 1024)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 100, 350, 250)
window.show()
sys.exit(app.exec_())
Answered By - ekhumoro
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.