wx.ScrolledWindow を使ったクライアント領域のスクロール

クライアント領域をスクロールに対応させるには、wx.ScrolledWindow を使うと簡単です。

    def __init__(self,parent=None):
        ...
        # スクロールバー
        XRCCTRL(self,'ID_FRAMEFIELD').SetScrollbars(1, 1, 1024, 1024)
        ...

メインウィンドウの子として持っているwx.ScrolledWindow をXRCCTRL() で取り出し、SetScrollbars 関数でスクロールの設定を行います。最初の二つの引数は、横方向と縦方向のスクロールピクセル数で、スクロールバーの端の△印をクリックしたときなんかのスクロール単位です。後ろの二つの引数はスクロールピクセル数をいくつ分スクロールさせるかと言う指定になっています。ちょっとややこしいのですが上記の場合だと1 ピクセルずつ1024 回スクロールするので合計1024 ピクセルの範囲をスクロールすることができます。SetScrollbars(8, 8, 128, 128) とした場合には8 ピクセルずつ128 回スクロールするので、これも合計1024 ピクセルの範囲をスクロールすることができます。 スクロールバーは、クライアント領域の幅・高さが、SetScrollbars で指定されたパラメータから計算されるスクロールする範囲よりも小さい場合に自動的に表示されます。


楽でよいのですが、スクロールするとクライアント領域の再描画がうまくいかず、スクロールアウト→スクロールインとしたところのクライアント領域が消えてしまいます。色々と対処方法を検索してみたところ、wx.BufferedPaintDC を作るときにwx.BUFFER_VIRTUAL_AREA を指定してやるとこの問題は一応解決しました。少々ちらつくようになってしまいましたが…

    def OnPaint(self, evt):
        dc = wx.BufferedPaintDC(XRCCTRL(self, ID_CANVAS), style=wx.BUFFER_VIRTUAL_AREA)
        ...

この手法をとると、描画が全般的にもっさりしてしまうので出来ればもうちょっといい解決案を調べたいところです。