0

我正在制作一个 Windows 应用程序wx.grid.Grid,它可以处理非常大的 Microsoft Excel 文档。目前,它会很快打开一个包含 17 列和 12 000 多行的文件,并且我可以流畅地滚动。(这是一个对来自自定义表类的数据进行操作的虚拟表。)

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

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

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

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

谢谢。

4

1 回答 1

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()

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

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

wx.grid.GridCellAttrProvider 或者,您可以从PyGridTableBase.SetAttrProvider(). 但是,这将阻止对表的直接访问。

于 2013-01-08T11:08:11.810 回答