wxChoiceの項目を操作に応じて変えたい場合の対処法を考える

プルダウンメニューから項目を選ばせたいとき、wxChoiceを使うことができる。こういうやつね。

このwxChoiceの項目を、動的に変える方法を考える。アプリを起動してから終了させるまで、項目を変える必要がないなら何もしなくても良いが、ある操作によって選ばせる項目(リスト)が変わるとき、どう対処するかということ。

基本ケース

変化前と変化後のリストの個数が同じ場合を、まず考える。例としては下のようなものがある。

この例では、3個の項目がある。リストとして、最初['1-1', '1-2', '1-3']だったものを、上のラジオボタンで「choice 2」を選ぶと、項目が['2-1', '2-2', '2-3']へ変化する。これを実現するには、SetStringメソッドが利用できる。これは簡単。
以下、実装例。

import wx

label1 = "Test label"

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

        self.rbox = wx.RadioBox(p, -1, "Test", choices=['choice 1', 'choice 2'])
        self.rbox.Bind(wx.EVT_RADIOBOX, self.check)

        self.cc1 = ['1-1', '1-2', '1-3']
        self.cc2 = ['2-1', '2-2', '2-3']
        self.chce = wx.Choice(p, -1, choices=self.cc1)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.rbox, 0, wx.ALL|wx.CENTER, 10)
        sizer.Add(self.chce, 0, wx.ALL|wx.CENTER, 10)

        p.SetSizer(sizer)
        Frm.Show()
        return 1

    def check(self, evt):
        num = self.rbox.GetSelection()
        if num == 0:
           for i in range(3):
               self.chce.SetString(i, self.cc1[i]) #ここでリストを変える。
        else:
           for i in range(3):
               self.chce.SetString(i, self.cc2[i]) #ここでリストを変える。

app = MyApp()
app.MainLoop()

応用ケース

次に、リストの個数を変えたい場合を考える。SetStringだけでは、項目数を操作することはできない。どうやるか。
リストの項目を一気に変えることはできないようなので、一つ一つ削除して新しい項目を加える方針でやってみる。
以下のメソッドを使う。

  • GetCount():項目数を得る。
  • Delete(n):n番目の項目を削除する。
  • Append(string):リストの最後にstringという項目を加える。

これらを使って以下のように書く。項目数を3から2へ、2から3へ変化させる場合。

import wx

label1 = "Test label"

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

        self.rbox = wx.RadioBox(p, -1, "Test", choices=['choice 1', 'choice 2'])
        self.rbox.Bind(wx.EVT_RADIOBOX, self.check)

        self.cc1 = ['1-1', '1-2', '1-3']
        self.cc2 = ['2-1', '2-2',]
        self.chce = wx.Choice(p, -1, choices=self.cc1)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.rbox, 0, wx.ALL|wx.CENTER, 10)
        sizer.Add(self.chce, 0, wx.ALL|wx.CENTER, 10)

        p.SetSizer(sizer)
        Frm.Show()
        return 1

    def check(self, evt):
        num = self.rbox.GetSelection()
        for i in range(self.chce.GetCount()): #リストを空にする
            self.chce.Delete(0) #リストの最初の項目を削除

        if num == 0:
           for i in range(3):
               self.chce.Append(self.cc1[i]) #空のリストに項目を追加
        else:
           for i in range(2):
               self.chce.Append(self.cc2[i])
        self.chce.SetSelection(0) #リストの最初の項目を表示する

app = MyApp()
app.MainLoop()

これでOK。