How to adjust the width of a table header and sort the rows

2

I have the following code to build a result table in Pyqt:

    def Tabla(self):
    #Boton de exportar a excel
    self.toolButton = QtWidgets.QToolButton()
    #self.toolButton.setGeometry(QtCore.QRect(30, 190, 41, 31))
    icon1 = QtGui.QIcon()
    icon1.addPixmap(QtGui.QPixmap(os.getcwd()+"\images\excel_tras.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)

    self.toolButton.setIcon(icon1)
    self.toolButton.setObjectName("toolButton")
    self.toolButton.clicked.connect(self.exporta)
    self.toolButton.setContentsMargins(50, 50, 50, 50)

    #Tabla
    self.table = QtWidgets.QTableView()
    self.table.setObjectName("table")

    self.tableWidget = QtWidgets.QTableWidget()
    self.tableWidget.setObjectName("tableWidget")
    self.tableWidget.setColumnCount(len(self.columnas))
    self.tableWidget.setRowCount(len(self.listaDatos))

    #Colocamos la cabecera
    columna = 0
    for ele in self.columnas:
        item = QtWidgets.QTableWidgetItem(ele)
        self.tableWidget.setHorizontalHeaderItem(columna, item)
        columna = columna + 1

    #Colocamos los datos
    fila = 0
    for lista in self.listaDatos:
        columna = 0
        for ele in lista:
            self.tableWidget.setItem(fila,columna, QtWidgets.QTableWidgetItem(ele))
            columna = columna + 1
        fila = fila + 1

    #Layout
    self.mainLayout.addWidget(self.tableWidget, 6, 0, 5, 7)
    self.mainLayout.addWidget(self.toolButton, 5, 5, 1, 1, QtCore.Qt.AlignRight)

And the appearance of the table is as follows: I would like the last column that you see in the image to see the full text ("Media uds sold last three months")

A senior take the question to see if they know some way that you can sort the values of a column ascending or descending as you click on the header.

Thank you!

    
asked by Adriana_0_0 20.08.2018 в 09:39
source

1 answer

0

Instead of adding the header as a row, consider using QTableWidget.setHorizontalHeaderLabels . Once this is done, you can use QHeaderView.setSectionResizeMode and specify that it be resized according to the content using QHeaderView.ResizeToContents . You can apply this to the header of the column you want by specifying the index or all of them.

As for ordering the columns, you simply have to enable it using the QTableWidget.setSortingEnabled() method, however, the columns are sorted by lexicogŕafico order. If you want your columns representing floats to be ordered as such you could create a class that derives from QTableWidgetItem and properly reimplement the method __lt__ ( rich comparison method ) using to establish the order between instances of the class.

As an example:

import sys
from PyQt5 import QtCore, QtWidgets 



class CustomTableWidgetItem(QtWidgets.QTableWidgetItem):
    def __init__ (self, value):
        super(CustomTableWidgetItem, self).__init__(str(value))

    def __lt__ (self, other):
        if (isinstance(other, CustomTableWidgetItem)):
            try:
                value  = float(self.data(QtCore.Qt.EditRole))
                other_value = float(other.data(QtCore.Qt.EditRole))
                return value < other_value
            except ValueError:
                pass
        return super().__lt__(other)


class Example(QtWidgets.QDialog):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.mainLayout = QtWidgets.QGridLayout()
        self.setLayout(self.mainLayout)
        self.columnas = ["Familia", "PVP", "PUC", "Margen", "Stock",
                         "Media uds vendidas últimos tres meses"
                         ]
        self.listaDatos = [["Salsas y vinagres", 3.04, 2.29, 0.25, 11.0, 4.47],
                           ["Especias y sal", 1.22, 0.9, 0.26, 38.0, 30.33],
                           ["Platos Prep.", 2.7, 1.9, 0.3, 0.0, 0]
                          ]  
        self.tabla()        


    def tabla(self):
        #Tabla
        self.table = QtWidgets.QTableView()
        self.table.setObjectName("table")

        self.tableWidget = QtWidgets.QTableWidget()
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(len(self.columnas))
        self.tableWidget.setRowCount(len(self.listaDatos))

        #Colocamos la cabecera
        self.tableWidget.setHorizontalHeaderLabels(self.columnas)
        header_view = self.tableWidget.horizontalHeader()
        idx = header_view.count() - 1
        header_view.setSectionResizeMode(idx, QtWidgets.QHeaderView.ResizeToContents)

        #Colocamos los datos
        for fila, lista in enumerate(self.listaDatos):
            for columna, elemento in enumerate(lista):
                self.tableWidget.setItem(fila, columna,
                                         CustomTableWidgetItem(elemento)
                                         )
        self.tableWidget.setSortingEnabled(True) 
        self.mainLayout.addWidget(self.tableWidget, 6, 0, 5, 7)



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialog = Example()
    dialog.exec_()
    sys.exit(app.exec_()) 

Another option would be to use QTableView instead of QTableWidget if nothing prevents you and QSortFilterProxyModel .

When you need the indexes of the elements when you iterate with a for in use enumerate , it is more efficient and simple than using a variable.

    
answered by 20.08.2018 / 14:11
source