I need to use a custom QtableView in Python to display and format data. The example app below shows a table with the first column of floats formatted as strings to get the proper number of decimals, the second column of floats displayed without formatting, and the third column contains strings. When clicking on columns, I want to sort my data. This works fine for strings and floats (columns #2 and #3), but not for column #1 with formatted floats as strings where it's sorted alphabetically rather than numerically. I've been googling for a while without finding a way to have something working with QtableView. Any clue on how to get both floats sorting and decimal formatting? Thanks & cheers Stephane import sys from PyQt5 import QtCore, QtWidgets from PyQt5.QtCore import * # Table model class TableModel(QtCore.QAbstractTableModel): def __init__(self, data): super(TableModel, self).__init__() self._data = data # Set columns headers self.horizontalHeaders = [''] * 3 self.setHeaderData(0, Qt.Horizontal, "Col #1\nfloats as string") self.setHeaderData(1, Qt.Horizontal, "Col #2\nfloats") self.setHeaderData(2, Qt.Horizontal, "Col #3\nstrings") def data(self, index, role): value = self._data[index.row()][index.column()] if role == Qt.DisplayRole: # convert col #1 from floats to string to get proper number of decimal formatting if index.column() == 0: return '%.4f' % value # otherwise display floats or strings for col #2 and #3 else: return value # Align values right if role == Qt.TextAlignmentRole: return Qt.AlignVCenter + Qt.AlignRight def rowCount(self, index): # The length of the outer list. return len(self._data) def columnCount(self, index): # The following takes the first sub-list, and returns # the length (only works if all rows are an equal length) return len(self._data[0]) def setHeaderData(self, section, orientation, data, role=Qt.EditRole): if orientation == Qt.Horizontal and role in (Qt.DisplayRole, Qt.EditRole): try: self.horizontalHeaders[section] = data return True except: return False return super().setHeaderData(section, orientation, data, role) def headerData(self, section, orientation, role=Qt.DisplayRole): if orientation == Qt.Horizontal and role == Qt.DisplayRole: try: return self.horizontalHeaders[section] except: pass return super().headerData(section, orientation, role) class MainWindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() # Create a TableView (not a TableWidget !!!) self.table = QtWidgets.QTableView() # sample data data = [ [4.2, 9.6, 1], [42.1, 0.0, 11], [3.1, 5.55, 2], [30.0, 3.55, 2222], [7.99, 8.99, 33], ] # Set table model self.model = TableModel(data) self.table.setModel(self.model) self.setCentralWidget(self.table) # Use proxy for column sorting proxyModel = QSortFilterProxyModel() proxyModel.setSourceModel(self.model) self.table.setModel(proxyModel) self.table.setSortingEnabled(True) # hide vertical headers self.table.verticalHeader().setVisible(False) # format horizontal headers stylesheet = "::section{Background-color:rgb(171,178,185);font-weight:bold}" self.table.setStyleSheet(stylesheet) self.table.setAlternatingRowColors(True) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.setMinimumSize(350, 250) window.setWindowTitle('Sorting column example') window.show() app.exec_() Continue reading...