QTableWidget 排序功能跟踪
来源:互联网 发布:结婚日子测算软件 编辑:程序博客网 时间:2024/05/29 15:11
最近为了实现QTableView的排序功能,通过网络搜索,未能找到解决办法,一时之下就跟踪了QTableWidget的排序功能,现在记录如下。
新建一个Qt工程,拖入QTableWidget控件,并随便输入几个初始值,添加一个按钮,然后添加一句排序代码:
this->ui->tableWidget->sortItems(0);
上边这一行就是跟踪入口。
具体实现
1.sortItems的实现
/*! Sorts all the rows in the table widget based on \a column and \a order.*/void QTableWidget::sortItems(int column, Qt::SortOrder order){ Q_D(QTableWidget); d->model->sort(column, order); horizontalHeader()->setSortIndicator(column, order);}
上述代码中Q_D宏,与本文无关,如有兴趣,请自行搜索。
排序功能的主要实现是靠model(QTableModule)中的sort函数实现的。
horizontalHeader()->setSortIndicator(column, order); 查看自带的文档介绍,主要是操作视图中的排序指示器的,所有也不用关心。
跟进sort函数:
void QTableModel::sort(int column, Qt::SortOrder order){ //1. QVector<QPair<QTableWidgetItem*, int> > sortable; QVector<int> unsortable; sortable.reserve(rowCount()); unsortable.reserve(rowCount()); for (int row = 0; row < rowCount(); ++row) { if (QTableWidgetItem *itm = item(row, column)) sortable.append(QPair<QTableWidgetItem*,int>(itm, row)); else unsortable.append(row); } //2. LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan); std::stable_sort(sortable.begin(), sortable.end(), compare); //3. QVector<QTableWidgetItem*> sorted_table(tableItems.count()); QModelIndexList from; QModelIndexList to; for (int i = 0; i < rowCount(); ++i) { int r = (i < sortable.count() ? sortable.at(i).second : unsortable.at(i - sortable.count())); for (int c = 0; c < columnCount(); ++c) { sorted_table[tableIndex(i, c)] = item(r, c); from.append(createIndex(r, c)); to.append(createIndex(i, c)); } } emit layoutAboutToBeChanged(); tableItems = sorted_table; changePersistentIndexList(from, to); // ### slow emit layoutChanged();}
排序的核心代码主要就是上边的函数。而这个函数又大致分了三个部分:
1.将要排序列的数据提取出来的放在vector中。
这里使用了两个vector:sortable用来保存有内容的部分。unsortable用来保存当前单元格为空的部分。由于QTableWiget中每一个单元格对应一个QTableWidgetItem,因此这里QPair中保存了该结构的指针以及当前单元格对应的行号。
2.排序部分。
排序函数:
bool QTableModel::itemLessThan(const QPair<QTableWidgetItem*,int> &left, const QPair<QTableWidgetItem*,int> &right){ return *(left.first) < *(right.first);}bool QTableModel::itemGreaterThan(const QPair<QTableWidgetItem*,int> &left, const QPair<QTableWidgetItem*,int> &right){ return (*(right.first) < *(left .first));}
从这里看使用QPair主要是为了通用吧,可以直接用first成员指代QPair中的第一个成员而不用关心其具体类型。
std::stable_sort 调用的是STL算法部分的排序函数,与sort函数相比,该函数在遇到相同值时将不改变原来的顺序,而sort可能会改变顺序。
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
这一句主要是根据参数order来选择是从大到小,还是从小到大。
而最终比较的实现是依靠QTableWidgetItem中的重载函数实现的。
/* Returns \c true if the item is less than the \a other item; otherwise returns false.*/bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const{ const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole); return QAbstractItemModelPrivate::variantLessThan(v1, v2);}
该函数中首先从QTableWidgetItem对象中取出具体的数据,然后调用variantLessThan比较最终的数据:
/*! \internal Return \c{true} if \a value contains a numerical type. This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort.*/bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVariant &v2){ switch(qMax(typeOfVariant(v1), typeOfVariant(v2))) { case 0: //integer type return v1.toLongLong() < v2.toLongLong(); case 1: //floating point return v1.toReal() < v2.toReal(); default: return v1.toString().localeAwareCompare(v2.toString()) < 0; }}
该函数主要是应对同一列的数据,数据类型不同而设置的。当数据类型不同时,将按照类型值较大的来实现排序。
static uint typeOfVariant(const QVariant &value){ //return 0 for integer, 1 for floating point and 2 for other switch (value.userType()) { case QVariant::Bool: case QVariant::Int: case QVariant::UInt: case QVariant::LongLong: case QVariant::ULongLong: case QVariant::Char: case QMetaType::Short: case QMetaType::UShort: case QMetaType::UChar: case QMetaType::ULong: case QMetaType::Long: return 0; case QVariant::Double: case QMetaType::Float: return 1; default: return 2; }}
根据上述描述,最终的数据排序只有三种类型:整形,浮点,字符串。
3.最终的实现。
这一部分看起来比较费力,目前暂时还未全部搞明白。
但是大致是分为两部分。
- 改变模型中的数据
sorted_table[tableIndex(i, c)] = item(r, c);
tableItems = sorted_table;//tableItems 是module中的内部成员。
以上是把数据部分排序,将单元格内容互换。
QTableWidgetItem *QTableModel::item(int row, int column) const{ return item(index(row, column));}QTableWidgetItem *QTableModel::item(const QModelIndex &index) const{ if (!isValid(index)) return 0; return tableItems.at(tableIndex(index.row(), index.column()));}
- 改变模型中的索引
QModelIndexList from;
QModelIndexList to;
changePersistentIndexList(from, to); // ### slow
4.最后部分:
emit layoutAboutToBeChanged(); 通知试图,模型将要改变。tableItems = sorted_table; //改变模型中的数据changePersistentIndexList(from, to); // ### slow 改变模型中的索引emit layoutChanged();//发送信号,模型已经改变,请更新数据。
以上是跟踪的总体过程,希望能对大家有所帮助。
- QTableWidget 排序功能跟踪
- QTableWidget 自定义排序
- QTableWidget排序问题
- QTableWidget如何实现换行功能?
- QTableWidget 点击标题栏 设置排序
- QTableWidget 点击标题栏 设置排序
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTableWidget
- QTablewidget
- QTableWidget
- 数据结构之栈(链式存储)——C++模板类实现
- 假标签
- visual studio code 键盘快捷键参考
- Java协变(共变)数组和类型擦除(covariant array & type erasure)
- UVA 12661 Funny Car Racing (Dijkstra最短路)
- QTableWidget 排序功能跟踪
- leetcode153. Find Minimum in Rotated Sorted Array
- Java里的String和StringBuffer
- 又是管理端入口引入的错误------类似事情过去发生, 现在发生, 未来还会发生!
- 啊!!!好吧不知道说什么!我的博客今天开通了!
- 阿里在线测评
- 面试题整理_Activity的奇葩生命周期
- Kali Rolling版本下的open-vm-tools安装
- 2017.3.4 pat甲级D题ZigZagging on a Tree