2015-04-23 208 views
4

我使用自定义QSortFilterProxyModel来通过重写filterAcceptsRow()来实现对QTableView的自定义过滤。当我改变过滤条件时,如何在整个表格上应用filterAcceptsRow()后,我的应用程序如何得到通知?QSortFilterProxyModel过滤完成信号

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

+0

Qt MVC不适用于可见项目的范围。模型不应该对视图有所了解。因为您可以为多个视图使用一个模型。 –

+0

我需要的是过滤处理完成时的通知。 – Mohamed

+0

没有这样的通知。因为排序正在“即时”进行。当你添加一个新的项目时 - 自动应用排序。 –

回答

5

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

+0

我在之前的评论中错了。我认为你是对的。投了票。上次,当我直接调用'layoutChanged'描述那里:http://stackoverflow.com/questions/16444558/how-to-force-qabstractitemview-recalculate-items-sizehints –

+0

非常感谢:)。 – Mohamed

+0

'QSortFilterProxyModel :: invalidateFilter()'不会发送它。它在'invalidate()'时发送得更早,但现在不是。 –

3

从我的观察(在Qt 4.8中),layout*()信号将在排序代理模型时触发,但如果您实施筛选则不会触发。文档也明确指代这些信号所指的项目的订单,并且自然过滤不会改变顺序,但仅影响行。

在这种情况下,只有rows*(...)信号(插入,删除等)将触发,具体取决于过滤器的功能。不利的一面是,如果过滤器被递归地应用(通常是这样),这些信号将在群众中激发,所以对于与单个结果行动相关联将不会有用。

为了克服这个问题,你可以在设置过滤器(不是invalidateFilter btw,因为它也不会触发布局信号)后调用invalidate()

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

但是最好处理过滤器字符串/ regExp /无论你自己使用基本方法(如setFilterFixedString(...))来设置它们,至少避免过滤两次 - 如果你已经重新使用, - 实现了filterAcceptsRow(...)

另一种方法是当设置排序或过滤,并通过使用Qt::QueuedConnection连接到它以确保它在过滤结束后执行时发出自己的信号。这就是我最终做的(更新表格的注册表),并且据我所知,它可以像预期的那样工作。

+0

这看起来也是这样。在更改过滤器表达式时,不会发布布局*()信号。 – Rafe