如何优化PyQt QSortFilterProxyModel过滤器重新实现?

时间:2010-08-13 05:18:32

标签: python qt4 pyqt pyqt4

我有一个重新实现的QSortFilterProxyModel acceptRows来实现自定义行为,我希望它不会过滤掉有效子项的项目。

class KSortFilterProxyModel(QSortFilterProxyModel):
    #FIXME: Funciona pero es endemoniadamente lento
    def __init__(self, parent=None):
        super(KSortFilterProxyModel, self).__init__(parent)
        self.__showAllChildren = False

    def showAllChildren(self):
        return self.__showAllChildren;

    def setShowAllChildren(self, showAllChildren):
        if showAllChildren == self.__showAllChildren:
            return
        self.__showAllChildren = showAllChildren
        self.invalidateFilter()

    def filterAcceptsRow (self, source_row, source_parent ):
        if self.filterRegExp() == "" :
            return True #Shortcut for common case

        if  super(KSortFilterProxyModel, self).filterAcceptsRow( source_row, source_parent) :
            return True

        #one of our children might be accepted, so accept this row if one of our children are accepted.
        source_index = self.sourceModel().index(source_row, 0, source_parent)
        for i in range( self.sourceModel().rowCount(source_index)):
            if self.filterAcceptsRow(i, source_index):
                return True

        return False

然而,这种方法似乎并不高效,因为有300个项目更新视图需要将近3秒钟,我想知道是否有更好的方法。

PD:这个课程基本上是我在KDE websvn

中找到的KSysGuard的翻译版本。

1 个答案:

答案 0 :(得分:1)

我没有看到你正在做的事情有什么明显错误。请记住,模型中的每个项都会调用filterAcceptsRow,这当然会变得缓慢,因为从C ++调用Python函数的开销是几毫秒。如果您有一个包含几百个项目的模型,这会相当快。再加上从Python调用的C ++函数的数量,你可以轻松地结束你注意到的3秒。

此外,QTableViewQSortFilterProxyModel做了大量聪明的事情,以便将发出的信号和所需的更新量保持在最低限度。遗憾的是,如果在重置过滤器后删除或添加的行非常分散在模型上,这会导致性能非常差。

在我们的项目中,我们决定在C ++中实现大多数基于项目的模型,至少对于那些为包含多个行或列的多少项的模型中的每个项调用的方法。但是,这可能不是您正在寻找的答案,尤其是如果您的更新延迟是由例如连接到同一型号的其他信号处理程序。发出信号通常与调用方法相同。

简而言之,您最好使用分析器来查看应用程序在大部分时间内花费的时间,如果模型中的每个项目调用一次(或甚至多次),则使用C ++