Как сортировать данные в 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"));
Обратите внимание, что этот класс должен использоваться только с числами, он не будет сортировать строки правильно (как в случае с принятым ответом).