wx.ListBox (wxPython) | Python-izm

ListBox

複数の要素の中から1つ、もしくは複数を選択出来るListBoxのサンプルです。単純なデータの表示に向いており、複数の要素を目視しながら項目を選択出来ます。

単一選択リスト

単一選択のリストボックスが最も基本的な形となります。引数choicesに表示する要素を渡し、styleLB_SINGLEを指定する事によって単一選択のリストが初期化されます。ただしデフォルトのスタイルが単一選択リストなので、特に明示せずとも単一の選択リストとなります。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2', 
                 'element_4', 'element_3', 'element_5')
listbox = wx.ListBox(panel, wx.ID_ANY, 
                     choices=element_array, style=wx.LB_SINGLE)

layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

常に1つの要素しか選択出来ません。もう1つを選択すると、既に選択されていた要素は選択解除されます。

複数選択リスト1

styleLB_MULTIPLEを指定すると、要素を複数選択出来るようになります。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2', 
                 'element_4', 'element_3', 'element_5')
listbox = wx.ListBox(panel, wx.ID_ANY, 
                     choices=element_array, style=wx.LB_MULTIPLE)

layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

クリックをする度に要素が選択されます。選択状態の要素を再度クリックすると、選択状態が解除されます。

複数選択リスト2

LB_EXTENDEDでも複数の要素を選択出来ます。このスタイルはShiftキーやCtrlキーと組み合わせて選択をする事で、複数の要素の選択が可能です。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2', 
                 'element_4', 'element_3', 'element_5')
listbox = wx.ListBox(panel, wx.ID_ANY, 
                     choices=element_array, style=wx.LB_EXTENDED)

layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

単純にクリックをしただけでは複数の要素は選択されません。特定のキーと組み合わせて選択をしてみましょう。

スクロールバー設定

要素数が多い場合、極端に要素名が長い場合など、リストボックスの表示領域に収まりきらないケースがあるかと思います。そういった時はスクロールバーを設定し、全要素をきちんと確認出来る様にしておく必要があります。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(400, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2', 'element_4',
                 'element_3', 'element_5', 'long_long__element')
listbox_1 = wx.ListBox(panel, wx.ID_ANY, size=(100, 200),
                       choices=element_array, style=wx.LB_HSCROLL)
listbox_2 = wx.ListBox(panel, wx.ID_ANY, size=(100, 200),
                       choices=element_array, style=wx.LB_ALWAYS_SB)
listbox_3 = wx.ListBox(panel, wx.ID_ANY, size=(100, 200),
                       choices=element_array, style=wx.LB_NEEDED_SB)

layout = wx.BoxSizer(wx.HORIZONTAL)
layout.Add(listbox_1, flag=wx.GROW | wx.ALL, border=3)
layout.Add(listbox_2, flag=wx.GROW | wx.ALL, border=3)
layout.Add(listbox_3, flag=wx.GROW | wx.ALL, border=3)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

LB_HSCROLLはリストボックスの横幅に収まりきらなかった場合に限り横スクロールを表示し、LB_ALWAYS_SBは要素数に関わらず常時縦スクロールを表示します。LB_NEEDED_SBはリストボックスの縦幅に収まりきらなかった場合に限り縦スクロールを表示する形です。

ソート指定

styleにCB_SORTを追加で指定すると、要素をソートして表示する事が出来ます。

import wx
 
application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))
 
panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')
 
element_array = ('element_1', 'element_2', 
                 'element_4', 'element_3', 'element_5')
listbox = wx.ListBox(panel, wx.ID_ANY, 
                     choices=element_array, style=wx.LB_SORT)
 
layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)
 
panel.SetSizer(layout)
 
frame.Show()
application.MainLoop()

複合スタイル

今までに紹介したスタイルを複数指定するには「 | 」を使用します。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 150))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('1', '2', '4', '3', '5', '6', '8', '7', '9')
listbox = wx.ListBox(panel, wx.ID_ANY, choices=element_array, 
                     style=wx.LB_EXTENDED | wx.LB_HSCROLL | wx.LB_NEEDED_SB | wx.LB_SORT)

layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

特定キーによる複数選択、横スクロールバー有り、縦スクロールバー有り、ソート指定が設定されています。

要素の追加

リストボックスが保持している既存の選択肢に、新しく要素を追加する場合はAppend、全ての要素を入れ替える場合はSetItemsを使用します。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2',
                 'element_4', 'element_3', 'element_5')
listbox_1 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)
listbox_2 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)

listbox_1.Append('element_6')

new_array = ('要素1', '要素2', '要素3')
listbox_2.SetItems(new_array)

layout = wx.GridSizer(rows=1, cols=2, gap=(0, 0))
layout.Add(listbox_1, flag=wx.GROW | wx.ALL, border=10)
layout.Add(listbox_2, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

それぞれのリストボックスが指定の値へ変更されています。

要素の削除

リストボックスが保持している既存の選択肢から、指定の要素を削除する場合はDeleteを(引数は削除したい要素のインデックス)、全ての要素を削除する場合はClearを使用します。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2',
                 'element_4', 'element_3', 'element_5')
listbox_1 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)
listbox_2 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)

listbox_1.Delete(1)
listbox_2.Clear()

layout = wx.GridSizer(rows=1, cols=2, gap=(0, 0))
layout.Add(listbox_1, flag=wx.GROW | wx.ALL, border=10)
layout.Add(listbox_2, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

listbox_1の要素が1つ、listbox_2の全要素が削除されています。

全要素、全要素数の取得

リストボックスが保持している全要素を取得するにはGetItemsを、要素数を取得する場合にはGetCountを利用します。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2',
                 'element_4', 'element_3', 'element_5')
listbox = wx.ListBox(panel, wx.ID_ANY, choices=element_array)

print('---------------------------------------')
for i in listbox.GetItems():
    print(i)

print('---------------------------------------')
print(listbox.GetCount())

layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

---------------------------------------
element_1
element_2
element_4
element_3
element_5
---------------------------------------
5

選択状態の設定・取得

リストボックスの選択状態の設定は、インデックスで指定する場合にSetSelection、要素名で指定する場合ではSetStringSelectionを使用します。選択値を取得する際は、単一選択のリストボックスの場合GetSelection、複数選択リストボックスの場合はGetSelectionsで選択されている要素のインデックス値が返ってきます。

import wx

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2',
                 'element_4', 'element_3', 'element_5')
listbox_1 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)
listbox_2 = wx.ListBox(panel, wx.ID_ANY, choices=element_array, style=wx.LB_EXTENDED)

listbox_1.SetSelection(3)
listbox_1.SetStringSelection('element_5')
print(listbox_1.GetSelection())

listbox_2.SetSelection(3)
listbox_2.SetStringSelection('element_5')
print(listbox_2.GetSelections())

layout = wx.GridSizer(rows=1, cols=2, gap=(0, 0))
layout.Add(listbox_1, flag=wx.GROW | wx.ALL, border=10)
layout.Add(listbox_2, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

listbox_1では1つの要素しか選択出来ないので、後に選択設定したelement_5が選択されている状態となります。

4
[3, 4]

イベント設定

リストボックスへイベントを設定するにはBindを使用します。引数は(イベント種別、イベント発生時に呼び出す関数)の順番で値を渡します。listbox_1のイベント定義はリストボックスの要素が選択されたら、listbox_2は要素がダブルクリックされたら、それぞれ該当の関数の呼び出しが行われます。

import wx

def listbox_select(event):
    obj = event.GetEventObject()
    frame.SetStatusText('listbox_1: ' + obj.GetStringSelection())

def listbox_double_click(event):
    obj = event.GetEventObject()
    frame.SetStatusText('listbox_2: ' + obj.GetStringSelection())

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))
frame.CreateStatusBar()

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

element_array = ('element_1', 'element_2',
                 'element_4', 'element_3', 'element_5')
listbox_1 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)
listbox_2 = wx.ListBox(panel, wx.ID_ANY, choices=element_array)

listbox_1.Bind(wx.EVT_LISTBOX, listbox_select)
listbox_2.Bind(wx.EVT_LISTBOX_DCLICK, listbox_double_click)

layout = wx.GridSizer(rows=1, cols=2, gap=(0, 0))
layout.Add(listbox_1, flag=wx.GROW | wx.ALL, border=10)
layout.Add(listbox_2, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

左のリストボックスは要素を選択すると、右のリストボックスは要素をダブルクリックするとステータスバーへ値をセットします。

内部データの設定・取得

リストボックスへ要素を追加する際、画面上へ表示させる文字列とは別に、内部データを保持する事が可能です。「名前」を表示させ「ID」を内部データとして埋め込んでおく、などの使用法が出来るようになるので非常に便利です。サンプルコードでは文字列を埋め込んでいますが、クラスなども埋め込み可能なので是非とも活用しましょう。

# -*- coding: utf-8 -*- 

import wx

def listbox_select(event):
    obj = event.GetEventObject()
    frame.SetStatusText(obj.GetClientData(obj.GetSelection()))

application = wx.App()
frame = wx.Frame(None, wx.ID_ANY, 'テストフレーム', size=(300, 200))
frame.CreateStatusBar()

panel = wx.Panel(frame, wx.ID_ANY)
panel.SetBackgroundColour('#AFAFAF')

listbox = wx.ListBox(panel, wx.ID_ANY)

listbox.Append('入門編', 'https://www.python-izm.com/introduction/')
listbox.Append('基礎編', 'https://www.python-izm.com/basis/')
listbox.Append('実践編', 'https://www.python-izm.com/practical/')
listbox.Append('wxPython', 'https://www.python-izm.com/gui/wxpython/')

listbox.Bind(wx.EVT_LISTBOX, listbox_select)

layout = wx.GridSizer(rows=1, cols=1, gap=(0, 0))
layout.Add(listbox, flag=wx.GROW | wx.ALL, border=10)

panel.SetSizer(layout)

frame.Show()
application.MainLoop()

リストボックスに表示されているサイト名ではなく、内部で保持していたURLを表示しています。