我可以在wxPython的wx.grid.Grid中加速优化GridCellAttr的使用吗?

时间:2013-01-08 08:32:55

标签: python wxpython wxwidgets wxgrid

我正在使用wx.grid.Grid创建一个Windows应用程序,它将处理非常大的Microsoft Excel文档。目前它打开一个包含17列和12 000多行的文件非常快,我可以顺利滚动。 (这是一个虚拟表,用于处理来自自定义表类的数据。)

无论如何,当我使用自定义网格单元属性对象时,问题就出现了,例如:

grid.SetAttr(row, col, SomeGridCellAttr('#FF0000'))

一旦连续的每个单元格都有一个自定义的网格单元格属性,网格的性能就会达到99.9%。而不是平滑滚动我很幸运,如果我每3秒重绘1次。我通过使用grid.SetColAttr修复了大多数这些实例,从而将性能恢复到之前的平滑度,但是 一个 的情况不起作用。应用程序迭代列中的每个单元格(12 000个单元格),对数据执行一些处理并根据结果应用自定义网格单元属性。一旦完成,网格将成为一个缓慢的噩梦。

有没有办法消除这种令人毛骨悚然的性能损失并保留自定义单元格属性?我怀疑对于那些了解网格内部工作原理及其细胞属性的人来说,答案非常简单。

感谢。

1 个答案:

答案 0 :(得分:3)

设置单元格属性会将新GridCellAttr添加到GridCellAttrProvider列表中。 随着列表的增长,查找单元格的特定属性(通过遍历列表并比较坐标)变得越来越慢。

您可以尝试通过实施自己的PyGridTableBase.SetAttrGetAttr(例如使用dict)加快速度:

编辑:更新了代码,允许覆盖属性并模拟默认的实施属性所有权。

class MyTable(wx.grid.PyGridTableBase):
    atts = {}

    def Hash(self,row,col):
        #FIXME: assumes a constant number of rows and rows > cols
        return col + row * self.GetNumberRows()

    def SetAttr(self,attr,row,col):
        HASH = self.Hash(row, col)
        if HASH in self.atts:
            # decrement usage count of existing attr
            self.atts[HASH].DecRef()
        #assign new attribute
        self.atts[HASH] = attr

    def GetAttr(self,row,col,kind):
        HASH = self.Hash(row, col)
        if HASH in self.atts:
            attr = self.atts[HASH]
            attr.IncRef() # increment reference count
            return attr
        return None

要允许设置整个行和列,您还必须实现:

    def SetRowAttr(self,attr,row):
        for col in range(self.GetNumberCols()):
            attr.IncRef() # increment reference count for SetAttr
            self.SetAttr(attr,row,col)
        attr.DecRef() # attr passed to SetRowAttr no longer needed

    def SetColAttr(self,attr,col):
        for row in range(self.GetNumberRows()):
            attr.IncRef() 
            self.SetAttr(attr,row,col)
        attr.DecRef()

注意:在将GridCellAttr传递给Set*Attr()时,默认实施将取得该属性的所有权。 要重用相同的属性(例如存储在类变量中),您必须Clone()或增加其使用次数(IncRef()) 在将其传递给Set*Attr()方法之前(克隆可能会增加内存消耗)。

上面的示例没有正确删除属性:SetAttr()可以检查无attr并减少指定坐标处的引用计数,然后从dict中删除条目。 可以通过为行和列添加dicts来优化SetCol/RowAttr(),类似于SetAttr()。然后GetAttr()可以检查行中的现有条目和col dict,并使用单元格dict中的属性合并/覆盖属性(这是默认实现使用的原则)。为了正确清理字典,请在DecRef之前的每个条目上调用.clear()

或者,您可以从wx.grid.GridCellAttrProvider派生并附加PyGridTableBase.SetAttrProvider()。但是,这会阻止直接访问表格。