QSortFilterProxyModel 过滤完成信号

QSortFilterProxyModel filtering complete signal

我正在使用自定义 QSortFilterProxyModel 通过覆盖 filterAcceptsRow() 来实现 QTableView 的自定义过滤。当我更改过滤条件时以及在整个 table 上应用 filterAcceptsRow() 后,如何通知我的应用程序?

基本上,我想在应用过滤后获得可见项的列表,目前我通过在我的模型中实现的自定义函数计算此列表,该函数迭代行并获得可见行的列表.这是低效的,因为如果两次调用此函数之间没有发生过滤操作,将产生相同的结果。

所有模型在排序、过滤或以任何其他可能影响视图的方式更改之前和之后都应发出 layoutAboutToBeChanged() and layoutChanged()

根据我的观察(在 Qt 4.8 中),layout*() 信号将在对代理模型进行排序时触发,但如果您实施过滤则不会。文档还明确引用了这些信号所指的项目的顺序,过滤自然不会改变顺序,只会影响行。

在这种情况下,只有 rows*(...) 信号(插入、移除等)会触发,具体取决于过滤器刚刚执行的操作。不利的一面是,如果过滤器是递归应用的(通常是这样),这些信号会大量触发,因此绑定到单个结果操作将无用。

要克服这个问题,您可以调用 invalidate() after setting filters (not invalidateFilter 顺便说一下,因为它也不会触发布局信号)。

因为这重新应用过滤 排序(过滤时不需要后者,但无法避免),layout*() 信号将两者都结束后开火。

但是最好自己处理过滤器 string/regExp/whatever 而不是使用基本方法(如 setFilterFixedString(...))来设置它们,至少避免过滤两次 - 开销不大无论如何,如果您已经重新实现了 filterAcceptsRow(...).

另一种方法是在设置排序或过滤时发出自己的信号,并使用Qt::QueuedConnection连接到它以确保它在过滤后执行确实结束了。这就是我最终所做的(更新 table 的寄存器),据我所知,它按预期工作。

您可以通过连接到代理模型发出的 QAbstractItemModel::rowsRemoved and QAbstractItemModel::rowsInserted 并将其连接到您自己的信号或插槽来获得“过滤完成信号”。

connect( filterProxyModel_, &QAbstractItemModel::::rowsRemoved,
        this, &MyWidget::onFilteringDone ) ;
connect( filterProxyModel_, &QAbstractItemModel::::rowsInserted,
        this, &MyWidget::onFilteringDone ) ;

其他信号如 layoutChanged 或 dataChanged 在过滤时不会发出。