0

wx.grid.Grid非常に大きな Microsoft Excel ドキュメントを処理する Windows アプリケーションを作成しています。現在、17 列と 12,000 行以上のファイルをすばやく開き、スムーズにスクロールできます。(これは、カスタム テーブル クラスのデータを操作する仮想テーブルです。)

とにかく、カスタム グリッド セル属性オブジェクトを使用すると問題が発生します。

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

行内のすべてのセルにカスタム グリッド セル属性が設定されると、グリッドのパフォーマンスは 99.9% 低下します。スムーズにスクロールする代わりに、3 秒ごとに 1 回再描画できればラッキーです。これらのインスタンスのほとんどをgrid.SetColAttr代わりに使用して修正しました。これにより、パフォーマンスが以前の滑らかさに戻りましたが、それが機能しない場合が1 つあります。アプリケーションは、列内のすべてのセル (12,000 セル) を繰り返し処理し、データに対して何らかの処理を実行し、結果に基づいてカスタム グリッド セル属性を適用します。それが完了すると、グリッドは動作が遅くなり、悪夢のようになります。

この恐ろしいパフォーマンス ヒットを取り除き、カスタム セル属性を保持する方法はありますか? グリッドの内部の仕組みとそのセル属性を知っている人にとって、答えは非常に簡単だと思います。

ありがとう。

4

1 に答える 1

3

セル属性を設定するGridCellAttrと、 のリストに新しい が追加されGridCellAttrProviderます。リストが大きくなるにつれて、(リストを反復して座標を比較することにより) セルの特定の属性を検索するのがますます遅くなります。

PyGridTableBase.SetAttr独自のものを実装することで高速化を試みることができますGetAttr(たとえば、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()

注:を に渡すGridCellAttrSet*Attr()、デフォルトの実装が属性の所有権を取得します。同じ属性 (たとえば、クラス変数に格納されている) を再利用するには、それをメソッドに渡す前に、その属性を再利用するかClone()、その使用回数 ( ) をインクリメントする必要があります(クローンを作成すると、メモリ消費量が増加する可能性があります)。IncRef()Set*Attr()

上記の例では、属性が適切に削除SetAttr()されていません。None 属性をチェックし、指定された座標で参照カウントを減らしてから、dict からエントリを削除できます。 SetCol/RowAttr()と同様に、行と列の辞書を追加することで最適化できますSetAttr()GetAttr()次に、行内の既存のエントリをチェックし、dict を照合して、属性をセル dict の属性とマージ/オーバーライドできます (これは、デフォルトの実装で使用される原則です)。dict(s) を適切にクリーンアップするには、 のDecRef前にすべてのエントリを呼び出します.clear()

または、 から派生さwx.grid.GridCellAttrProvider せてアタッチすることもできますPyGridTableBase.SetAttrProvider()。ただし、これにより、テーブルへの直接アクセスが妨げられます。

于 2013-01-08T11:08:11.810 に答える