QSortFilterProxyModel 对多列进行排序

2022-01-02 00:00:00 model qt sorting c++ model-view-controller

我正在尝试实现一个可在多个列上排序的表.Qt 的 QSortFilterProxyModel 仅支持对一列进行排序(至少在 Qt 4.6.2 中).

I am trying to implement a table that is sortable on more than one column. Qt's QSortFilterProxyModel only supports sorting on one column (at least in Qt 4.6.2).

我在 github 上找到了 dimkanovikov 的此解决方案,但它缺少对添加行的动态更新.我的意思是,模型发生了变化,并且 beginInsertRows()、beginRemoveRows()、它们对应的 end..-methods 和 dataChanged() 信号被发出.理想情况下,我只想更新这些行,但模型至少应该对此类更改做出反应.

I've found this solution by dimkanovikov on github, but it lacks dynamic updating on added rows. What I mean by this, is that the model is changed and the beginInsertRows(), beginRemoveRows(), their corresponding end..-methods and the dataChanged() signals are emitted. Ideally I would like to only these rows to be updated, but the model should at least react to such changes.

Qt 网站上还有另一个常见问题解答项目,可以对 QTableWidget 进行排序,但它也缺乏动态更新.

There's another FAQ item on Qt's site that sorts a QTableWidget, but it lacks dynamic updating, too.

我是 Qt 的新手,我想得到一些关于我应该如何处理的建议.

I am new to Qt and I'd like to get some pointers on how I should go about this.

推荐答案

有一个稍微不雅的解决方案,它总是用于对多列进行排序.

There's one slightly inelegant solution, that is always used to sort multiple columns.

您必须继承 QSortFilterProxyModel 并重新实现 bool lessThan(const QModelIndex &rLeft, const QModelIndex &rRight) const.检查所有列,而不是仅在两个给定索引之间进行比较:

You have to subclass QSortFilterProxyModel and reimplement bool lessThan(const QModelIndex &rLeft, const QModelIndex &rRight) const. Instead of only comparing between the two given indices, check all the columns:

int const left_row  = rLeft.row();
int const right_row = rRight.row();

int const num_columns = sourceModel()->columnCount();
for(int compared_column = rLeft.column(); compared_column<num_columns; ++compared_column) {
    QModelIndex const left_idx = sourceModel()->index(left_row, compared_column, QModelIndex());
    QModelIndex const right_idx = sourceModel()->index(right_row, compared_column, QModelIndex());

    QString const leftData = sourceModel()->data(left_idx).toString();
    QString const rightData = sourceModel()->data(right_idx).toString();

    int const compare = QString::localeAwareCompare(leftData, rightData);
    if(compare!=0) {
        return compare<0;
    }
}

return false;

然后您可以在您的 QSortFilterProxyModel 子类上调用 sort(0) ,它将对所有列进行排序.如果您希望在模型数据更改时动态重新排序已排序的行,也不要忘记调用 setDynamicSortFilter(true).

Then you can call sort(0) on your QSortFilterProxyModel subclass and it will sort all the columns. Also don't forget to call setDynamicSortFilter(true) when you want the sorted rows to be dynamically resorted when the model data changes.

要支持按升序或降序对任意列进行排序,您必须将此信息保存在 QList 中,并在调用 lessThan 时进行相应比较.在列表中,您将按优先级顺序排列列,并以相同的顺序进行比较.您还应该以某种预定义的顺序对其他非活动"列进行排序,否则默认情况下它们不会被排序.

To support sorting on arbitrary columns in ascending or descending order, you would have to keep this info in a QList and compare accordingly when lessThan is called. In the list you would have the columns in order of their priority and do the comparisons in the same order. You should also sort the other "inactive" columns in some predefined order, otherwise they will not be sorted by default.

相关文章