我在视图和模型(QTableView
)之间有一个QSortFilterProxyModel
QStandardItemModel
。问题是当我调用sort()时,我无法恢复表中行的原始顺序。我试图通过在飞行中将模型代理更改为QIdentityProxy
但无济于事,因为唯一的变化是行重新编号但订单保持排序。
是否可能以某种方式“取消”数据?我认为,在这种情况下,代码是不必要的,但如果被问到则会发布。
我在Win x64上使用Qt5
P.S。:同样的问题在2009年发布here,但从未得到回答。
答案 0 :(得分:3)
恢复初始未排序状态(已测试)
sortModel->setSortRole(Qt::InitialSortOrderRole);
sortModel->invalidate();
答案 1 :(得分:2)
我的理解是你需要将排序恢复到默认状态?如果您在重置排序时以其返回默认值的方式覆盖QSortFilterProxyModel :: lessThan()函数,即:
return QSortFilterProxyModel::lessThan(left, right);
,并在排序“启用”时自定义排序结果?我想您还需要使用QAbstractItemModel :: reset()将代理模型重置为其原始状态。但是,它将重新填充整个模型数据,您将丢失选择信息。
答案 2 :(得分:2)
重点是手动排序按列-1(还原)和正常列号排序,并以某种方式拦截QHeaderView
和QSortFilterProxyModel
之间的通信。
所以,利用@ 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);
}
这样我可以在QTableView
为sortingEnabled
时使用由true
完成的自动排序处理。我已经尝试研究当点击表头以引导排序时Qt内部发生了什么,但是失败了,所以停止了这个解决方案。
我仍然不确定这种方式QTableView
负责设置正确的排序指示是否正确,而不是QHeaderView
本身(因为我认为此功能属于标题)。< / p>
答案 3 :(得分:0)
我喜欢使用左上角按钮来恢复顺序(即,按该按钮作为标题的行号排序)。这适用于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)
答案 4 :(得分:0)
这对我来说最有效:
QSortFilterProxyModel *proxyModel = myTableView->model ();
proxyModel->sort (-1);
请注意,这不会更新TableView的标题指示符,所以在调用上面的代码之前,我也在调用:
myTableView->horizontalHeader ()->setSortIndicator (0, Qt::DescendingOrder);
我真的不喜欢它,但我还没有找到使用TableView或HorizontalHeader来重置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排序执行两次。