QSortFilterProxyModel对多列进行排序

kos*_*eat 2 c++ sorting model-view-controller qt model

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

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

在Qt的网站上有另一个FAQ项目可以对QTableWidget进行排序,但它也缺乏动态更新.

我是Qt的新手,我想知道如何解决这个问题.

rom*_*mor 7

您可以设置的排序作用QSortFilterProxyModel,以不同的东西,则默认Qt::DisplayRole使用setSortRole(Qt::UserRole).然后,在模型的data()方法中,如果使用角色调用它,则返回正确的排序键Qt::UserRole,例如通过连接所涉及列的字符串.


kos*_*eat 5

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

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

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;
Run Code Online (Sandbox Code Playgroud)

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

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