Qt之 QTableWidget 列排序
1、常规的QTableWidget的排序接口
void QTableView::setSortingEnabled(bool enable) // 允许点击表头进行排序
void QTableWidget::sortItems(int column, Qt::SortOrder order = Qt::AscendingOrder) // 排序接口
例子:
table->setSortingEnabled(true); // 运行排序
table->sortItems(0); // 对 0 列排序, 默认升序
2、含有数字字符的字符串排序
常规的排序是以QString序进行排序,也就是u16序,如下图:
对于混杂有数字的字符串排序如上图,就不太符合人的认知。
对于混合有数字的排序,需要重写 QTableWidgetItem的比较函数 operator<():
bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
所以自定义排序则需要扩展QTableWidgetItem,自定义字符串排序算法很好写,但是不需要。因为Qt自身提供了一个十分方便的类 :QCollator
virtual bool operator<(const QTableWidgetItem& other) const override
{
QCollator collator;
collator.setNumericMode(true);
auto ret = collator.compare(this->text(), other.text());
if (ret < 0)
return true;
else
return false;
}
3、保存原始序
在构造item的时候,顺便保存行号为原始序
item = new ATableWidgetItem;
item->setData(ATableWidgetItem::OriginSort,0); // 保存原始序
使用一个 flag 来控制排序
virtual bool operator<(const QTableWidgetItem& other) const override
{
if (sortToOrigin) {
return this->data(OriginSort).toInt() < other.data(OriginSort).toInt();
} else {
QCollator collator;
collator.setNumericMode(true);
auto ret = collator.compare(this->text(), other.text());
if (ret < 0)
return true;
else
return false;
}
}
完整Demo
#include <QDebug>
#include <QLocale>
#include <QRandomGenerator>
#include <QtWidgets>
#define qout qDebug() << __FILE__ << __LINE__
#define qrand QRandomGenerator::global()
QStringList testStr = { "hello" };
/**
* @brief 扩展 QTableWidgetItem 类, 重写 operator<() 函数
*/
class ATableWidgetItem : public QTableWidgetItem {
public:
using QTableWidgetItem::QTableWidgetItem; // 继承构造
enum {
OriginSort = Qt::UserRole + 1
};
public:
virtual bool operator<(const QTableWidgetItem& other) const override
{
if (sortToOrigin) {
return this->data(OriginSort).toInt() < other.data(OriginSort).toInt();
} else {
QCollator collator;
collator.setNumericMode(true);
auto ret = collator.compare(this->text(), other.text());
if (ret < 0)
return true;
else
return false;
}
}
static bool sortToOrigin; // 声明原始序标志
};
bool ATableWidgetItem::sortToOrigin = false; // 定义原始序标志
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
QWidget w;
auto HBox = new QHBoxLayout(&w);
auto table = new QTableWidget;
HBox->addWidget(table);
auto btn = new QPushButton("显示表格原始序");
HBox->addWidget(btn);
auto row = 5, col = 3;
table->setRowCount(row);
table->setColumnCount(col);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
auto* item = table->item(i, j);
if (!item) {
item = new ATableWidgetItem;
// item = new QTableWidgetItem;
table->setItem(i, j, item);
if (j == 0)
item->setData(ATableWidgetItem::OriginSort, i);
}
auto txt = testStr[qrand->bounded(testStr.length())]
+ "_"
+ QString::number(qrand->bounded(20)) + "_world";
item->setText(txt);
}
}
table->setSortingEnabled(true);
QObject::connect(btn, &QPushButton::clicked, [&] {
ATableWidgetItem::sortToOrigin = true;
table->sortItems(0);
table->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder);
ATableWidgetItem::sortToOrigin = false;
});
w.resize(500, 300);
w.show();
return a.exec();
}