5

我在视图和模型之间有一个QTableViewwith ( )。问题是当我调用 sort() 时,我无法恢复表中行的原始顺序。我试图通过将模型代理更改为即时但无济于事来实现这一点,因为唯一的变化是对行重新编号但顺序保持排序。QSortFilterProxyModelQStandardItemModelQIdentityProxy

是否有可能以某种方式“取消排序”数据?我认为,在这种情况下,该代码是不必要的,但如果被问到会发布。

我在 Win x64 上使用 Qt5

PS:同样的问题早在 2009 年就在这里发布过,但从未得到回答。

4

6 回答 6

5

恢复初始未排序状态(已测试)

    sortModel->setSortRole(Qt::InitialSortOrderRole);
    sortModel->invalidate();

QSortFilterProxyModel::​setSortRole(int role)

于 2015-01-23T10:15:27.243 回答
3

关键是在按列-1(恢复)和正常列号排序之间手动决定排序,QHeaderViewQSortFilterProxyModel以某种方式拦截之间的通信。

因此,使用@vahancho 回答的一些见解,我设法实现了这样的排序:

class ProxyModel : public QSortFilterProxyModel
{
    Q_OBJECT
public:
    ProxyModel(QObject* parent = 0);

signals:
    void askOrder(int column, Qt::SortOrder order);

public slots:
    //! override of automatically called function
    void sort(int column, Qt::SortOrder order) 
    { 
        emit askOrder(column, order); 
    }

    //! real sorting happens here
    void doSort(int column, Qt::SortOrder order) 
    { 
        QSortFilterProxyModel::sort(column, order); 
    }
};

在父母方面,我进行了适当的连接和检查:

ResultsTable::ResultsTable(QWidget *parent) : QTableView(parent)
{
    /*...*/
    p_Header = new QHeaderView(this);
    p_Sort = new ProxyModel(this);
    connect(this, &ResultsTable::doSort, p_Sort, &ProxyModel::doSort);
    connect(p_Sort, &ProxyModel::askOrder, this, &ResultsTable::setSorting);
    /*...*/
    setSortingEnabled(true);
}

void ResultsTable::setSorting(int column, Qt::SortOrder order)
{
    if (p_Header->sortIndicatorOrder() == Qt::AscendingOrder && p_Header->isSortIndicatorShown() && m_PreviousSort == column)
    {
        p_Header->setSortIndicator(column, Qt::DescendingOrder);
        p_Header->setSortIndicatorShown(false);
        column = -1;
    }
    else
    {
        p_Header->setSortIndicatorShown(true);
    }
    m_PreviousSort = column;
    emit doSort(column, order);
}

这样我可以使用QTableViewwhen sortingEnabledis完成的自动排序处理true。我试图研究当单击表头以诱导排序时 Qt 内部发生了什么,但失败了,因此停止使用此解决方案。

我仍然不确定这种方式QTableView是否正确负责设置正确的排序指示,而不是QHeaderView它本身(因为我认为这个功能应该属于标题)。

于 2013-09-10T10:16:21.617 回答
2

我的理解是您需要将排序恢复到默认状态?如果您在想要重置排序时以返回默认值的方式覆盖 QSortFilterProxyModel::lessThan() 函数会怎样,即:

return QSortFilterProxyModel::lessThan(left, right);

,以及排序“启用”时的自定义排序结果?我认为您还需要使用 QAbstractItemModel::reset() 将代理模型重置为其原始状态。但是,它将重新填充整个模型数据,您将丢失选择信息。

于 2013-09-05T14:09:51.563 回答
2

这对我最有效:

QSortFilterProxyModel *proxyModel = myTableView->model ();
proxyModel->sort (-1);

请注意,这不会更新 TableView 的标题指示符,因此在调用上面的代码之前,我还要调用:

myTableView->horizontalHeader ()->setSortIndicator (0, Qt::DescendingOrder);

我不是很喜欢它,但我还没有找到使用 TableView 或 Horizo​​ntalHeader 来重置 QSortFilterProxyModel 排序的方法。

这是完整的代码:

// Block QHeaderView signals so sorting doesn't happen twice
myTableView->horizontalHeader ()->blockSignals (true);

// Update the sort indicator to be the same as it was when the TableView was created
myTableView->horizontalHeader ()->setSortIndicator (0, Qt::DescendingOrder);

// Reset sorting
QSortFilterProxyModel *proxyModel = myTableView->model ();
proxyModel->sort (-1);

// Unblock QHeaderView signals
myTableView->horizontalHeader ()->blockSignals (false);

注意:我暂时阻止水平标题信号以防止 QSortFilterProxyModel 排序执行两次。

于 2018-01-04T20:09:23.750 回答
1

我喜欢使用左上角按钮来恢复顺序(即按该按钮作为标题的行号排序)。这适用于 pyqt 5.9 中的标准类:

def __init__(self):
    #...
    tb = self.tableView # has sorting enabled and SortIndicator shown
    proxy = QSortFilterProxyModel(self)
    proxy.setSourceModel(self.model)
    tb.setModel(proxy)
    btn = tb.findChild(QAbstractButton)
    if btn:
        btn.disconnect()
        btn.clicked.connect(self.disableSorting)
    tb.horizontalHeader().setSortIndicator(-1, 0)

def disableSorting(self):
    self.tableView.model().sort(-1)
    self.tableView.horizontalHeader().setSortIndicator(-1, 0)
于 2017-09-25T14:14:40.527 回答
0

从文档:

QSortFilterProxyModel 可以按列 -1 排序,在这种情况下它返回到底层源模型的排序顺序。

所以,正如@eTHP 所说,成功sort(-1)了!

于 2021-12-13T21:36:36.713 回答