ここでは、リストコントロール、ツリーなどに小さい画像を表示する方法を解説します。 小さい画像は wxPythonに登録されているものを使います。そのために wxArtProvider というクラスを使います。 リストコントロールなどに表示させるためには、画像を直接指定するのではなくて、 いったん wxImageList というリストに画像を登録しておいて、 コントロールからは wxImageList オブジェクトの番号を指定して表示することになります。
まず、小さい画像(アイコン)を表示することから始めます。 wxPythonにはいくつかの画像が、wx.ART_GO_UP、wx.ART_FOLDER などのIDで登録されています。 すべての画像とIDは下の画像のようになります。
この画像IDからビットマップオブジェクトを作ります。
### ex1502.py ### 1: import wx 2: 3: class MyApp(wx.App): 4: def OnInit(self): 5: frame = wx.Frame(None, -1, "wxPython", size=(150,100)) 6: FindBmap = wx.ArtProvider.GetBitmap(wx.ART_FIND) 7: StBmap = wx.StaticBitmap(frame, -1, FindBmap, (10,20)) 8: StText = wx.StaticText(frame, -1, "wx.ART_FIND", pos=(40,20)) 9: frame.Show() 10: return 1 11: 12: app = MyApp() 13: app.MainLoop()
方法自体は簡単で、wx.ArtProvider の GetBitmapメソッドの引数に
画像IDを入れるだけです。
wx.ArtProvider.GetBitmap(画像ID)
wxBitmapじゃなく、wxImageオブジェクトを作るメソッドは無いようです。
次に、タイトルの wxImageListの解説です。 wxImageListは、ビットマップオブジェクトのリストを作るだけですが、 リストコントロールなどではこのオブジェクトを使うので、あらかじめ作っておく必要があります。
### ex1503.py ###
1: import wx
2:
3: class MyApp(wx.App):
4: def OnInit(self):
5: frame = wx.Frame(None, -1, "wxPython", size=(220,130))
6: NFileBmap = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE)
7: MFileBmapOrg = wx.ArtProvider.GetBitmap(wx.ART_MISSING_IMAGE)
8: MFileImg = wx.ImageFromBitmap(MFileBmapOrg)
9: MFileBmap = MFileImg.Scale(16,16).ConvertToBitmap()
10: SpirImg = wx.Image("picture/btn.png")
11: SpirBmap = SpirImg.Scale(16,16).ConvertToBitmap()
12:
13: Imglist = wx.ImageList(16,16)
14: Imglist.Add(NFileBmap)
15: Imglist.Add(MFileBmap)
16: Imglist.Add(SpirBmap)
17:
18: NFileStBmap = wx.StaticBitmap(frame, -1, Imglist.GetBitmap(0), (10,10))
19: MFileStBmap = wx.StaticBitmap(frame, -1, Imglist.GetBitmap(1), (10,40))
20: SpirStBmap = wx.StaticBitmap(frame, -1, Imglist.GetBitmap(2), (10,70))
21: NFileStText = wx.StaticText(frame, -1, "wx.ART_NORMAL_FILE", pos=(40,10))
22: MFileStText = wx.StaticText(frame, -1, "wx.ART_MISSING_IMAGE", pos=(40,40))
23: SpirStText = wx.StaticText(frame, -1, "Spiral", pos=(40,70))
24: frame.Show()
25: return 1
26:
27: app = MyApp()
28: app.MainLoop()
wxImageListの定義では、画像の幅と高さを設定します。
重要なのは「wxImageList に追加する画像はすべてこの幅と高さにしておく」ということです。
ここでは、13行目の wxImageListの定義で画像の大きさを (16,16) にしてるので、
各画像をそれに合わせます。
wx.ImageList(幅、高さ)
| Add(BITMAP) | BITMAPを追加する |
| GetBitmap(n) | n番目のBITMAP画像を返す |
| Replace(n, BITMAP) | n番目の画像をBITMAPに置き換える |
6行目のNFileBmap (ART_NORMAL_FILE)は元々(16,16)なのでそのままです。
7行目のNFileBmap (ART_MISSING_IMAGE)は(32,32)なので縮小する必要があります。
しかし、wxBitmapオブジェクトには縮小するメソッドはないので(切り抜くのはあります)、
一旦 wxImageオブジェクトに置き換えて縮小し、また wxBitmapオブジェクトに戻すことになります。
それが、8行目で wxImageオブジェクトにして、9行目で Scaleメソッドで縮小して
wxBitmapオブジェクトに変換しています。
10行目は画像ファイル (btn.png)を読み込んでいます。これも縮小する必要があるので
wxImageオブジェクトとして読み込んでいます。
11行目で縮小して wxBitmapオブジェクトに変換しています。
18〜20行目で、GetBitmapメソッドを使って各画像を取り出して表示してます。
ここでは wxImageListからビットマップ画像を取り出してますが、
リストコントロールなどでは、番号を指定するだけで画像が取り出されます。
wxListCtrl で画像を表示します。はじめにバーチャルじゃない wxListCtrlの場合です。
### ex1504.py ### 1: import wx 2: 3: class ImgList(wx.ImageList): 4: def __init__(self): 5: wx.ImageList.__init__(self, 16,15) 6: BackBmap = wx.ArtProvider.GetBitmap(wx.ART_GO_BACK) 7: FowrBmap = wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD) 8: self.Add(BackBmap) 9: self.Add(FowrBmap) 10: 11: class ImgListCtrl(wx.ListCtrl): 12: def __init__(self, parent): 13: wx.ListCtrl.__init__(self, parent, -1, style= wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES) 14: self.AssignImageList(ImgList(), wx.IMAGE_LIST_SMALL) 15: self.InsertColumn(0, "Col 0") 16: self.InsertColumn(1, "Col 1") 17: self.InsertImageItem(0, 0) 18: self.SetStringItem(0, 1, 'ART_GO_BACK') 19: self.InsertImageStringItem(1, 'ART_GO_FORWARD', 1) 20: self.SetStringItem(1, 1, '', 0) 21: self.InsertStringItem(2, '') 22: self.SetStringItem(2, 1, 'ART_GO_FORWARD', 1) 23: self.SetColumnWidth(0,-1) 24: self.SetColumnWidth(1,-1) 25: 26: class MyApp(wx.App): 27: def OnInit(self): 28: frame = wx.Frame(None, -1, "wxPython", size=(350,150)) 29: MyImgList = ImgListCtrl(frame) 30: MainSZ = wx.BoxSizer() 31: MainSZ.Add(MyImgList, 1, wx.EXPAND | wx.ALL, 20) 32: frame.SetSizer(MainSZ) 33: frame.Show() 34: return 1 35: 36: app = MyApp() 37: app.MainLoop()
| AssignImageList(IMAGELIST, wx.IMAGE_LIST_SMALL) | IMAGELISTを使えるようにする |
| InsertImageItem(r, n) | r行目を追加して、最初の列に n番目のBITMAP画像を表示する |
| InsertImageStringItem(r, TEXT, n) | r行目を追加して、最初の列に n番目のBITMAP画像と文字列TEXTを表示する |
| SetStringItem(r, c, TEXT, n) | r行c列目に n番目のBITMAP画像と文字列TEXTを表示する |
| SetItemColumnImage(r, c, n) | r行c列目に n番目のBITMAP画像を表示する |
3〜9行目は ImageList の定義で、11行目からリストコントロールの定義です。
まず、14行目の AssignImageListメソッドでIMAGELISTを割り当ててます。
この引数の wx.IMAGE_LIST_SMALL は、リファレンスだと
wx.IMAGE_LIST_NORMALというのもあるのですが、SMALLでないとエラーになります。
17行目と19行目で、行を追加する時に最初の列に画像を表示してます。
上のメソッドの表にあるように、行を追加する場合は画像だけか画像と文字両方なのかでメソッドが別になってます
(文字だけの場合も入れて3種類になります)。
画像の指定は ImageListで定義された順番の数字だけになります。
0列目以外は、SetStringItemメソッドだけです。
画像を表示しない場合は、引数の最後の画像番号は省略します。
次に、バーチャルリストの場合です。
### ex1505.py ###
1: import wx
2:
3: LIST = [('', 'ART_GO_FORWARD'), ('ART_GO_BACK', ''), ('', 'ART_GO_BACK')]
4:
5: class ImgList(wx.ImageList):
6: def __init__(self):
7: wx.ImageList.__init__(self, 16,15)
8: BackBmap = wx.ArtProvider.GetBitmap(wx.ART_GO_BACK)
9: FowrBmap = wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD)
10: self.Add(BackBmap)
11: self.Add(FowrBmap)
12:
13: class ImgListCtrl(wx.ListCtrl):
14: def __init__(self, parent):
15: wx.ListCtrl.__init__(self, parent, -1,
16: style= wx.LC_REPORT | wx.LC_VRULES | wx.LC_HRULES | wx.LC_VIRTUAL)
17: self.AssignImageList(ImgList(), wx.IMAGE_LIST_SMALL)
18: self.InsertColumn(0, "Col 0")
19: self.InsertColumn(1, "Col 1")
20: self.SetColumnWidth(0,150)
21: self.SetColumnWidth(1,150)
22: self.SetItemCount(len(LIST))
23:
24: def OnGetItemText(self, row, col):
25: return LIST[row][col]
26:
27: def OnGetItemColumnImage(self, row, col):
28: if (row, col) in [(0,0), (1,1)]:
29: return 1
30: elif (row, col) in [(1,0), (2,1)]:
31: return 0
32: else:
33: return -1
34:
35: class MyApp(wx.App):
36: def OnInit(self):
37: frame = wx.Frame(None, -1, "wxPython", size=(350,150))
38: MyImgList = ImgListCtrl(frame)
39: MainSZ = wx.BoxSizer()
40: MainSZ.Add(MyImgList, 1, wx.EXPAND | wx.ALL, 20)
41: frame.SetSizer(MainSZ)
42: frame.Show()
43: return 1
44:
45: app = MyApp()
46: app.MainLoop()
ImageListの定義は同じです。
バーチャルリストで画像を表示するには、OnGetItemColumnImage関数を定義しておきます。
OnGetItemColumnImage関数の引数は、self、 行番号、列番号になります。
関数が返す値は整数で、これがImageListの画像番号になります。
画像を表示しない部分には、最後のelse で return -1 と、-1を返しておかないと
リストの表示が上手く出来ません。
ツリーで画像を表示する方法です。
### ex1506.py ###
1: import wx
2:
3: Dict = {
4: 'ARIA':['Alicia', 'Akari'],
5: 'HIMEYA':['Akira', 'Aika'],
6: 'ORANGE':['Athena', 'Alice'],
7: }
8:
9: class ImgList(wx.ImageList):
10: def __init__(self):
11: wx.ImageList.__init__(self, 16,15)
12: CloseBmap = wx.ArtProvider.GetBitmap(wx.ART_FOLDER)
13: OpenBmap = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN)
14: BackBmap = wx.ArtProvider.GetBitmap(wx.ART_GO_BACK)
15: FowrBmap = wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD)
16: self.Add(CloseBmap)
17: self.Add(OpenBmap)
18: self.Add(BackBmap)
19: self.Add(FowrBmap)
20:
21: class Tree(wx.TreeCtrl):
22: def __init__(self, parent):
23: wx.TreeCtrl.__init__(self, parent, -1)
24: self.AssignImageList(ImgList())
25: IdRoot = self.AddRoot("Company")
26: for theCom in Dict.keys():
27: IdCom = self.AppendItem(IdRoot, theCom, 0)
28: for theWnd in Dict[theCom]:
29: self.AppendItem(IdCom, theWnd, 2,3)
30:
31: self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnExpand)
32: self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnCollapsed)
33: self.SortChildren(IdRoot)
34: self.Expand(IdRoot)
35:
36: def OnExpand(self, event):
37: ID = event.GetItem()
38: self.SetItemImage(ID, 1)
39:
40: def OnCollapsed(self, event):
41: ID = event.GetItem()
42: self.SetItemImage(ID, 0)
43:
44: class MyApp(wx.App):
45: def OnInit(self):
46: frame = wx.Frame(None, -1, "wxTree", size=(200,260))
47: self.MyTree = Tree(frame)
48: MainSizer = wx.BoxSizer(wx.VERTICAL)
49: MainSizer.Add(self.MyTree, 1, wx.EXPAND | wx.ALL, 20)
50: frame.SetSizer(MainSizer)
51: frame.Show()
52: return 1
53:
54: app = MyApp()
55: app.MainLoop()
| AssignImageList(IMAGELIST) | IMAGELISTを使えるようにする |
| AppendItem(ID, TEXT, m, n) | IDを親として項目を追加し、文字列をTEXT、選択されてない時の画像をm番目, 選択された時をn番目のビットマップにする |
| SetItemImage(ID, n) | 項目IDの画像をn番目のビットマップにする |
wxTreeCtrlでは、項目が選択されたかどうかで、2種類の画像を指定することができます。
一方、項目が開いたか開いてないかで画像を変更する場合は、自分でイベント関数を作って制御する必要があります。
31行目で項目が開いた時のイベント wx.EVT_TREE_ITEM_EXPANDEDを関数OnExpandに結びつけます。
32行目で項目が閉じた時のイベント wx.EVT_TREE_ITEM_COLLAPSEDを関数OnCollapsedに結びつけます。
36行目からと40行目からの関数の中はほとんど同じで、
項目のIDを得て、その項目の画像を SetItemImageメソッドで置き換えてます。
最後に、ノートブックで画像を表示する方法です。
### ex1507.py ### 1: import wx 2: 3: class ImgList(wx.ImageList): 4: def __init__(self): 5: wx.ImageList.__init__(self, 32,32) 6: ErrBmap = wx.ArtProvider.GetBitmap(wx.ART_ERROR) 7: HelpBmap = wx.ArtProvider.GetBitmap(wx.ART_HELP) 8: self.Add(ErrBmap) 9: self.Add(HelpBmap) 10: 11: class MyApp(wx.App): 12: def OnInit(self): 13: frame = wx.Frame(None, -1, "wxNote", size=(200,150)) 14: Nb = wx.Notebook(frame, -1) 15: Nb.AssignImageList(ImgList()) 16: Panel1 = wx.Panel(Nb, -1) 17: Panel2 = wx.Panel(Nb, -1) 18: Nb.AddPage(Panel1, "Error", imageId = 0) 19: Nb.AddPage(Panel2, "Help", imageId = 1) 20: StText1 = wx.StaticText(Panel1, -1, "Error", pos=(20,10)) 21: StText2 = wx.StaticText(Panel2, -1, "Help", pos=(20,10)) 22: 23: MainSizer = wx.BoxSizer(wx.VERTICAL) 24: MainSizer.Add(Nb, 1, wx.EXPAND | wx.ALL, 20) 25: frame.SetSizer(MainSizer) 26: frame.Show() 27: return 1 28: 29: app = MyApp() 30: app.MainLoop()
| AssignImageList(IMAGELIST) | IMAGELISTを使えるようにする |
| AddPage(PAGE, TEXT,imageId = n) | PAGEをページとして追加し、タブの表示をTEXTとn番目のビットマップにする |
ノートブックのAddPageメソッドは、正確には TEXT の次にページを選択するかしないかの
True, False の引数があるので、それを省略して画像番号を入れるには imageId = n と書く必要があります。
ここで使っている画像 wx.ART_ERROR, wx.ART_HELP は本来 (32,32) サイズなのですが、見ての通り縮小されています。