排序QtTableModel - QTableView未更新

4
我实现了一个自定义的QAbstractTableModel,并且我正在使用std::vector来存储我的数据对象。
现在我想要实现sort()方法,以便通过列对表进行排序。基本上我所做的就是:
void SBStateTableModel::sort (int column, Qt::SortOrder order)
{
emit layoutAboutToBeChanged();

switch (column)
{
case Address:
    if (order == Qt::DescendingOrder)
        std::sort(states.begin(), states.end(), addr_comp_desc);
    else
        std::sort(states.begin(), states.end(), addr_comp_asc);

default:
    return;
}

emit layoutChanged();
}

但仅发出layoutChanged()并不会重新绘制视图。当标记一行并循环遍历它们时,在它们被突出显示时进行更新。
文档还提到了更新持久性索引。这里的一些人建议,实际上这是没有必要的。我甚至不知道该怎么做。使用persistentIndexList()获取列表,然后必须对其进行排序。但是std::sort不是稳定的排序。我不确定如何将持久性索引与我的向量索引匹配。
编辑: 在“ case”中只缺少了一个“ break”!因此,在发出layoutChanged信号之前,函数将返回。

也许你需要在表格视图上调用 QTableView::sortByColumn(int, Qt::SortOrder) 函数来对列进行排序? - vahancho
点击列标题即可实现此功能。信号和槽已连接。我可以确认我的排序程序正在被调用。首先,我在其中有一个qDebug()输出,其次,如果我在表格中突出显示这些行,我可以看到新的(预期)值。 - Benjamin Maurer
2个回答

5

天啊!

我准备深入研究Qt源代码。但是当我单步执行我的代码时,我看到光标跳转到'default'情况下的返回语句。

我只是忘记在我的switch-case中添加'break'了!这只是一个简单的“穿透”错误 :(( 现在使用"layoutChanged"完美地解决了问题。


2
我刚刚做了这件事。首先,您需要将标题信号连接到您创建的排序方法。这是一个Python示例,因此您需要将其适应C ++:
model = SBStateTableModel()
table = QtGui.QTableView()
table.setModel(model)

table.setSortingEnabled(True)

当您进行排序时,整个视图将发生变化 - 或者至少大部分视图会发生变化。因此,发出 modelReset 信号将导致视图改变。模型重置是调用最低效的信号之一,因为它会导致整个视图被重新绘制。然而,在排序时,大部分视图都会发生变化。

emit modelReset();

您还可以发出dataChanged信号,表示所有数据都已更改。 dataChanged信号可能更快。

Python:

self.dataChanged.emit(self.index(0, 0), self.index(self.rowCount()-1, self.columnCount()-1))

C++:

(在 QTableView 的子类中发出 dataChanged 信号)

auto m = model();
emit dataChanged (m->index(0, 0), m->index(m->rowCount()-1, m->columnCount()-1));

1
reset() 会销毁用户选择等状态。我建议不要在模型中搞乱排序,而是在模型之上使用 QSortFilterProxyModel。 - Frank Osterfeld
1
好的观点。我没有考虑到这一点。最好使用dataChanged信号。dataChanged信号不会影响用户的选择。用户的选择仍然在那些单元格上,但是这些单元格的数据将会改变。你可能希望选择被移除。 - justengel
尝试过这个: emit dataChanged(this->createIndex(0,0,0), this->createIndex(states.size()-1, HEADERS_LEN-1,1));但是没有成功 :( - Benjamin Maurer
@BenjaminMaurer 我认为它应该只是:emit dataChanged(this->index(0,0), this->index(this->rowCount()-1, this->columnCount()-1))。我认为这就是C++中的正确写法。语法基本上仍然是相同的。 - justengel
@JustinEngel 那个方法是重载的。我尝试过没有id参数的版本,使用2个参数的版本。结果一样。 - Benjamin Maurer
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接