Search code examples
qtformattingqtablewidgetitem

QT QtableWidgetItem display formated data and sort by original data


In a column in a QTableWidget I want to display some double values. By doing the following, I get my desired display:

double value = 1234.567;
QTableWidgetItem* qti = new QTableWidgetItem(QString::number(value , 'f', 4));

Now, if I enable sorting on the table and sort the values in this column, it will sort as strings. So 90.0000 will come be "larger" than 800.0000 for example (9 > 8).

If I do this instead:

QTableWidgetItem* qti = new QTableWidgetItem();
qti->setData(Qt::DisplayRole, value);

or

QTableWidgetItem* qti = new QTableWidgetItem(QString::number(value , 'f', 4));
qti->setData(Qt::DisplayRole, value);

I can sort my column correctly, but I "lose" the formmating (12.0000 is displayed as 12).

I've also tried like this:

QTableWidgetItem* qti = new QTableWidgetItem();
qti->setData(Qt::UserRole, value);
qti->setData(Qt::DisplayRole, QString::number(value, 'f', 4));

How can I format the display of the values, while still enabling sorting?

(In all code snippets above, the QTableWidgetItems' are added by:

table->setItem(rowNumber, colNumber, qti);

where table is a QTableWidget)


Solution

  • You do it wrong. Let's do it right. The solution is to subclass QTableWidgetItem.

    class CustomTableWidgetItem : public QTableWidgetItem
    {
    
    public:
    
        CustomTableWidgetItem(const QString txt = QString("0"))
            :QTableWidgetItem(txt)
        {
        }
    
        bool operator <(const QTableWidgetItem& other) const
        {
            qDebug() << "Sorting numbers";
            return text().toFloat() < other.text().toFloat();
           // text() is part of QTableWidgetItem, so you can write it as QTableWidgetItem::text().toFloat() as well
        }
    };
    

    Example insertions

        ui->tableWidget->setSortingEnabled(false);
        ui->tableWidget->insertRow(0);
        ui->tableWidget->setItem(0, 0, new CustomTableWidgetItem(QString::number(90.0005, 'f', 4)));
        ui->tableWidget->insertRow(1);
        ui->tableWidget->setItem(1, 0, new CustomTableWidgetItem(QString::number(800.0003, 'f', 4)));
        ui->tableWidget->insertRow(2);
        ui->tableWidget->setItem(2, 0, new CustomTableWidgetItem(QString::number(200.0010, 'f', 4)));
        ui->tableWidget->insertRow(3);
        ui->tableWidget->setItem(3, 0, new CustomTableWidgetItem(QString::number(200.0020, 'f', 4)));
        ui->tableWidget->setSortingEnabled(true);
    

    Sorting behaviour is as expected

    ascending

    90.0005
    200.0010
    200.0020
    800.0003
    

    descending

    800.0003
    200.0020
    200.0010
    90.0005
    

    PS: Remember to turn off sorting before you insert bew items.