編集可能な表をwxListCtrlで作成する

wxListCtrlで作成した表において、セルの値を直接編集することはできない。SetStringItemメソッドで、値を変えることはもちろんできるが。ここでの直接編集とは、マウスで表のセルをクリックして値をキーボードから入力するようなことを指す。

wxGridなどを使って表を作成すれば、セルの編集にも対応できるが、比較的簡単にきれいな表を描けるのでどうしてもwxListCtrlを使いたい。そこで、wxListCtrlで作成した表で値を直接編集し、その編集した値をどう取得すればいいのか、というのが今回の話。

セルの値を編集できるwxListCtrl

セルの値を編集するために、wx.lib.mixins.listctrl.TextEditMixinを継承して使う。下はテストコード。

import wx
import wx.lib.mixins.listctrl as listmix

class TestList(wx.ListCtrl, listmix.TextEditMixin):
    def __init__(self, parent, ID, pos=wx.DefaultPosition,
                 size=wx.DefaultSize, style=0):
        wx.ListCtrl.__init__(self, parent, ID, pos, size, style)

        listmix.TextEditMixin.__init__(self)

        self.InsertColumn(0, "#")
        self.InsertColumn(1, "Time")
        self.InsertColumn(2, "Value")

        self.SetColumnWidth(0, 100)
        self.SetColumnWidth(1, 100)
        self.SetColumnWidth(2, 100)
        self.InsertStringItem(0, '1')
        self.InsertStringItem(1, '2')
        self.InsertStringItem(2, '3')

        self.SetStringItem(0, 1, "0")
        self.SetStringItem(0, 2, "0.777")
        self.SetStringItem(1, 1, "0.1")
        self.SetStringItem(1, 2, "1.222")
        self.SetStringItem(2, 1, "0.2")
        self.SetStringItem(2, 2, "5.333")

class MyApp(wx.PySimpleApp):
    def OnInit(self):
        Frm = wx.Frame(None, -1, 'Title', size=(300, 250))
        self.p = wx.Panel(Frm, -1)

        jl = TestList(self.p, 0, size=(300, 100), 
                      style=wx.LC_REPORT|wx.LC_HRULES)
        
        Frm.Show()
        return True

app = MyApp()
app.MainLoop()

これを実行すると、下の画面が立ち上がる。


これで、セルをクリックすると編集可能になる。でも、全てのセルが編集できるようになってしまうのが辛いところ。編集できるセルとできないセルを指定できればいいのに。


値を編集後、リターンキーで確定する。


wxListCtrlで作成した表の値を取得する

値を変えられるようにしたはいいが、変えた値を取得することができなければその値を利用することはできない。そこで、セルの値をどうやって求めるかの方法も合わせて検討する。

列のタイトルをクリックしたときに、その列すべての値を取得するようにしてみる。先ほどのテストコードに、イベントを加える。

import wx
import wx.lib.mixins.listctrl as listmix

class TestList(wx.ListCtrl, listmix.TextEditMixin):
    def __init__(self, parent, ID, pos=wx.DefaultPosition,
                 size=wx.DefaultSize, style=0):
        wx.ListCtrl.__init__(self, parent, ID, pos, size, style)

        listmix.TextEditMixin.__init__(self)

        self.InsertColumn(0, "#")
        self.InsertColumn(1, "Time")
        self.InsertColumn(2, "Value")

        self.SetColumnWidth(0, 100)
        self.SetColumnWidth(1, 100)
        self.SetColumnWidth(2, 100)
        self.InsertStringItem(0, '1')
        self.InsertStringItem(1, '2')
        self.InsertStringItem(2, '3')

        self.SetStringItem(0, 1, "0")
        self.SetStringItem(0, 2, "0.777")
        self.SetStringItem(1, 1, "0.1")
        self.SetStringItem(1, 2, "1.222")
        self.SetStringItem(2, 1, "0.2")
        self.SetStringItem(2, 2, "5.333")

        self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)

    def OnColClick(self, evt):
        col = evt.GetColumn()
        print self.GetItem(0, col).GetText()
        print self.GetItem(1, col).GetText()
        print self.GetItem(2, col).GetText()

class MyApp(wx.PySimpleApp):
    def OnInit(self):
        Frm = wx.Frame(None, -1, 'Title', size=(300, 250))
        self.p = wx.Panel(Frm, -1)

        jl = TestList(self.p, 0, size=(300, 100), 
                      style=wx.LC_REPORT|wx.LC_HRULES)
        
        Frm.Show()
        return True

app = MyApp()
app.MainLoop()

GetItem.GetText()で値を取得できる。変更後のセルの値もちゃんと得られている。