Как сортировать данные в QTableWidget?

У меня есть QTableWidget, и первый столбец содержит числа от 1 до 1000. Теперь мне нужно отсортировать таблицу на основе этого первого столбца.

Я использую функцию 'sortItems (int column, Qt:: AscendingOrder)', но она отображается как: 1, 10, 100, 1000, 101, 102,...

Но мне нужен результат как: 1, 2, 3, 4...., 1000.

Я использую файл csv для заполнения таблицы. Может ли кто-нибудь помочь мне в этом?

Ответ 1

Самый простой способ - это, вероятно, подкласс QTableWidgetItem, а затем реализовать < оператора, чтобы быть умным о том, что вы сортируете числа, а не строки.

class MyTableWidgetItem : public QTableWidgetItem {
    public:
        bool operator <(const QTableWidgetItem &other) const
        {
            return text().toInt() < other.text().toInt();
        }
};

Затем, когда вы заполняете свою таблицу, вы можете передать ей экземпляры ваших пользовательских элементов, которые знают, как правильно сортировать себя, а не общие.

Ответ 2

Значения сортируются как строки, потому что вы сохранили их как таковые в модели.

QVariant может запомнить исходный тип данных, если вы позволите ему выполнить преобразование, и оператор сравнения из этого типа будет использоваться при сортировке:

// Get the value from the CSV file as a numeric type
int valueFromCsvFile = ...;

// don't do this
QTableWidgetItem *item = new QTableWidgetItem(QString::number(valueFromCsvFile));

// but do this instead
QTableWidgetItem *item = new QTableWidgetItem;
item.setData(Qt::EditRole, valueFromCsvFile);    

Редактор ячейки также будет адаптироваться к типу QVariant:

  • QSpinBox для int,
  • QDoubleSpinBox для double и float,
  • QDateTimeEdit для QDateTime
  • ...

Ответ 3

Один из способов, который работал в моей ситуации, -

1) перед заполнением таблицы отключите сортировку:

table.setSortingEnabled(False)

2) введите числовые строки с пробелами и сделайте все строки в столбце одинаковой длины:

('    '+numStr)[-4:]

3) после заполнения таблицы, включите сортировку:

table.setSortingEnabled(True)

Это фиксировало проблему сортировки строк и порядковый номер.

Ответ 4

Я не знаю, работал ли принятый ответ, но с Qt5.1 это не так. Чтобы работать, определение operator< должно соответствовать виртуальному определению из qtablewidget.h.

Еще одно интересное дополнение - сортировать элементы, которые имеют числа, но начинаются с знака валюты (например, $ или ) или заканчиваются на %.

Вот обновленный код:

class TableNumberItem : public QTableWidgetItem
{
public:
    TableNumberItem(const QString txt = QString("0"))
        :QTableWidgetItem(txt)
    {
    }
    bool operator <(const QTableWidgetItem &other) const
    {
        QString str1 = text();
        QString str2 = other.text();

        if (str1[0] == '$' || str1[0] == '€') {
            str1.remove(0, 1);
            str2.remove(0, 1); // we assume both items have the same format
        }

        if (str1[str1.length() - 1] == '%') {
            str1.chop(1);
            str2.chop(1); // this works for "N%" and for "N %" formatted strings
        }

        double f1 = str1.toDouble();
        double f2 = str2.toDouble();

    return str1.toDouble() < str2.toDouble();
    }
};

Затем вы добавляете элементы, содержащие числа, используя что-то вроде этого:

myTableWidget->setItem(row, col, new TableNumberItem("$0"));

Обратите внимание, что этот класс должен использоваться только с числами, он не будет сортировать строки правильно (как в случае с принятым ответом).