Skip to main content
 首页 » 编程设计

python之如何优化 PyQt QSortFilterProxyModel 过滤器的重新实现

2025年05月04日8傻小

我有一个重新实现的 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 秒来更新 View ,我想知道是否有更好的方法。

PD:这个类基本上是我在 KDE websvn 中找到的 KSysGuard 类的翻译

请您参考如下方法:

我看不出您所做的有任何明显的错误。请记住,filterAcceptsRow 会为模型中的每个项目 调用,这当然会很慢,因为从 C++ 调用 Python 函数的开销很少毫秒。如果您有一个包含几百个项目的模型,这会很快加起来。再加上从 Python 调用的 C++ 函数的数量,您可以很容易地以您注意到的 3 秒结束。

此外,QTableView 和 QSortFilterProxyModel 做了很多聪明的事情来将它们发出的信号和所需的更新量保持在最低限度。遗憾的是,如果在过滤器重置后删除或添加的行非常分散在您的模型中,这会导致非常糟糕的性能。

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

简而言之,您最好使用探查器来查看您的应用程序将大部分时间花在哪里,如果这些方法在模型中的每个项目中被调用一次(或什至多次),则使用 C++ .