wxPythonのサンプルのwx.lib.editor.Editorはwx.ScrolledWindowを継承して作られている。
wx.ScrolledWindowは、wx.Panelのサブクラスで、
右と下にスクロールバーが表示されるので、子コンポーネントをスクロール出来る。
(wx.Panelもスクロールバーを表示できるが、wx.ScrollBarの方がやりやすい)
自作のテキストエディタもwx.ScrolledWindowを継承することにする。
wx.ScrolledWindowは一見単独では使わなそうなので、
これを継承してテキスト入力欄を作るのは気持ち悪いが。
wx.lib.editor.Editorのソースから、行のスクロールの部分だけを抜き出すことにする。
小1時間ほど格闘。
理解できなかった。
wx.lib.editor.Editorでは、EVT_SCROLLWIN_LINEUP、EVT_SCROLLWIN_LINEDOWN、
EVT_SCROLLWIN_PAGEDOWN等で場合わけをしたり、何かゴチャゴチャやっているが、
下のように、とにかくスクロールバーが変化したら再描画すれば良い様に思える。
import wx from itertools import islice import string class EditCtrl(wx.ScrolledWindow): def __init__(self, parent): wx.ScrolledWindow.__init__(self, parent, -1) self.lines = [c.join(str(i) for i in xrange(100)) for c in string.ascii_lowercase] self.font = wx.Font(pointSize=25, family=wx.FONTFAMILY_TELETYPE, style =wx.NORMAL, weight=wx.FONTWEIGHT_NORMAL, faceName=u"MSゴシック" ) dc = wx.ClientDC(self) dc.SetFont(self.font) self.lineHeight = dc.GetCharHeight() self.SetScrollbars(0, self.lineHeight, 0, len(self.lines)) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_SCROLLWIN, self.OnScroll) def OnScroll(self, evt): self.Refresh() evt.Skip() def OnPaint(self, event): cw, ch = self.GetClientSize() buf = wx.EmptyBitmap(cw, ch) dc = wx.BufferedPaintDC(self, buf) dc.SetFont(self.font) dc.SetBackgroundMode(wx.SOLID) dc.Clear() ypos = self.GetScrollPos(wx.VERTICAL) nlines = ch // self.lineHeight if ch % self.lineHeight: nlines += 1 for i, line in islice(enumerate(self.lines), ypos, ypos + nlines): dc.DrawText(line, 0, (i - ypos)*self.lineHeight) def main(): app = wx.PySimpleApp() f = wx.Frame(None, -1) e = EditCtrl(f) f.Show() app.MainLoop() if __name__ == "__main__": main()