リンク

2017年5月3日水曜日

pythonでGUIツールを作る ~ ListCtrl (大アイコン、小アイコン、リスト)~

今回は数あるウィジットの中でもよく使用されるListCtrlについて書いていきます。

wxPythonのListCtrlには以下の4つのスタイルがあります。

  • wx.LC_ICON
  • wx.LC_SMALL_ICON
  • wx.LC_LIST
  • wx.LC_REPORT

今回はその中のwx.LC_ICON、wx.LC_SMALL_ICON、wx.LC_LISTの3つを一気にご紹介します。

それではいきなりスクリプトです。
# -*- coding: UTF-8 -*-

import wx

class App(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(500, 500), style=wx.DEFAULT_FRAME_STYLE)

        # ステータスバー
        self.CreateStatusBar()

        # パネル
        p = wx.Panel(self, wx.ID_ANY)

        # ListCtrl0 大アイコン - - - - - - - - - - - - - - - - - - - - - - - - - - -
        self.listctrl = wx.ListCtrl(p, wx.ID_ANY, style=wx.LC_ICON)
        self.listctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.item_select)

        # イメージリスト
        imagelist = wx.ImageList(32, 32)
        imagelist.Add(wx.Icon("a.png", wx.BITMAP_TYPE_PNG))
        imagelist.Add(wx.Icon("b.png", wx.BITMAP_TYPE_PNG))
        imagelist.Add(wx.Icon("c.png", wx.BITMAP_TYPE_PNG))
        imagelist.Add(wx.Icon("d.png", wx.BITMAP_TYPE_PNG))

        # ListCtrlにイメージリストを割り当て
        self.listctrl.AssignImageList(imagelist, wx.IMAGE_LIST_NORMAL)

        # ListCtrlにアイテムを追加
        for x in range(4):
            self.listctrl.InsertItem(x, 'item_%s' % x, x)

        # ListCtrl1  小アイコン - - - - - - - - - - - - - - - - - - - - - - - - - - -
        self.listctrl1 = wx.ListCtrl(p, wx.ID_ANY, style=wx.LC_SMALL_ICON)

        # イメージリスト
        imagelist1 = wx.ImageList(16, 16)
        imagelist1.Add(wx.Icon("a.png", wx.BITMAP_TYPE_PNG))
        imagelist1.Add(wx.Icon("b.png", wx.BITMAP_TYPE_PNG))
        imagelist1.Add(wx.Icon("c.png", wx.BITMAP_TYPE_PNG))
        imagelist1.Add(wx.Icon("d.png", wx.BITMAP_TYPE_PNG))

        # ListCtrlにイメージリストを割り当て
        self.listctrl1.AssignImageList(imagelist1, wx.IMAGE_LIST_SMALL)

        # ListCtrlにアイテムを追加
        for y in range(4):
            self.listctrl1.InsertItem(y, 'item_%s' % y, y)

        # ListCtrl1  リスト - - - - - - - - - - - - - - - - - - - - - - - - - - -
        self.listctrl2 = wx.ListCtrl(p, wx.ID_ANY, style=wx.LC_LIST)

        # イメージリスト
        imagelist2 = wx.ImageList(16, 16)
        imagelist2.Add(wx.Icon("a.png", wx.BITMAP_TYPE_PNG))
        imagelist2.Add(wx.Icon("b.png", wx.BITMAP_TYPE_PNG))
        imagelist2.Add(wx.Icon("c.png", wx.BITMAP_TYPE_PNG))
        imagelist2.Add(wx.Icon("d.png", wx.BITMAP_TYPE_PNG))

        # ListCtrlにイメージリストを割り当て
        self.listctrl2.AssignImageList(imagelist2, wx.IMAGE_LIST_SMALL)

        # ListCtrlにアイテムを追加
        for z in range(4):
            self.listctrl2.InsertItem(z, 'item_%s' % z, z)

        layout = wx.BoxSizer(wx.VERTICAL)
        layout.Add(self.listctrl, flag=wx.EXPAND | wx.ALL, border=10, proportion=1)
        layout.Add(self.listctrl1, flag=wx.EXPAND | wx.ALL, border=10, proportion=1)
        layout.Add(self.listctrl2, flag=wx.EXPAND | wx.ALL, border=10, proportion=1)
        p.SetSizer(layout)

        self.Show()

    def item_select(self, event):
        """ アイテム選択時のイベントハンドラー """
        # 選択したアイテムのインデックスを取得する
        select_index = self.listctrl.GetFirstSelected()

        # インデックスのアイテムからテキストを取得する
        item_label = self.listctrl.GetItemText(select_index)

        # ステータスバーの文字列を変更
        self.SetStatusText(item_label + "を選択しました")


app = wx.App()
App(None, wx.ID_ANY, 'ListCtrl')
app.MainLoop()

<結果> ↓ ↓ ↓



※画像ファイルは各自でご用意ください。

上記スクリプトでは1つのパネル上に3つのListCtrlを配置しています。
# インスタンス化とスタイルの指定
self.listctrl = wx.ListCtrl(p, wx.ID_ANY, style=wx.LC_ICON)
self.listctrl1 = wx.ListCtrl(p, wx.ID_ANY, style=wx.LC_SMALL_ICON)
self.listctrl2 = wx.ListCtrl(p, wx.ID_ANY, style=wx.LC_LIST)
ListCtrlをインスタンス化する際、style引数にそれぞれの値を指定します。
大アイコンの場合はデフォルトスタイルがwx.LC_ICONなので、
self.listctrl = wx.ListCtrl(p, wx.ID_ANY)
でもOK。

# アイテムの追加
self.listctrl.InsertItem(x, 'item_%s' % x, x)
アイテムを追加するにはInsertItem関数を用います。
引数は(インデックス、ラベル文字列、イメージリストのインデックス)です。
但し、イメージリストのインデックスはデフォルトで-1が入るため、イメージリストは必須ではありません。

# イメージリストの割り当て
self.listctrl.AssignImageList(imagelist, wx.IMAGE_LIST_NORMAL)
引数は(イメージリスト、タイプ)です。
イメージリストについての詳細はwxPythonのイメージリストをご覧ください。
このタイプはwx.IMAGE_LIST_NORMALとwx.IMAGE_LIST_SMALLのどちらかを指定できます。
wx.IMAGE_LIST_NORMALは今回のwx.LC_ICONに使用し、wx.IMAGE_LIST_SMALLはwx.LC_SMALL_ICON、wx.LC_LIST、wx.LC_REPORTで使用します。


今回はwx.ListCtrlの大アイコン、小アイコン、リストの3スタイルをご紹介しました。
この3つは表示方法が違うだけで、その他は同じです。
次回は最も使用頻度の高い「wx.LC_REPORT」をご紹介する予定です。


3 件のコメント:

  1. これはレポートビューでもそうなのですが、ドラッグ&ドロップで複数選択できるようです。
    その選択されたもの全てを取得する方法はありますか?
    --戻り値の例--
    Item0とItem1が選択された場合:
    ["Item0","Item1"]

    返信削除
    返信
    1. コメントありがとうございます。

      ご質問の件ですが、選択されている項目を一括取得するメソッドはありませんでした。

      よって、地道に取得していくしかないようです。
      参考までに私は次のように記述しました。

      ※サンプルスクリプトにボタンを追加し、下記のメソッドをクリックイベントへ適用してください。

      ※コメント内では前方のスペースが前詰めになってしまいましたので、アンダーバーを代用しております。 プログラムをコピーして使用する場合は、前方のアンダーバーを半角スペースに置き換えてください。

      ____def click(self,event):
      ________""" クリックイベント """
      ________# ---ここから選択項目のインデックスを取得
      ________selection = []
      ________index = self.listctrl.GetFirstSelected()

      ________# 未選択の場合は終了
      ________if index == -1:
      ____________return
      ________else:
      ____________selection.append(index)

      ________while len(selection) != self.listctrl.GetSelectedItemCount():
      ____________index = self.listctrl.GetNextSelected(index)
      ____________selection.append(index)
      ________# ---ここまで

      ________# ここから項目取得
      ________selectitem = []
      ________for i in selection:
      ____________selectitem.append(self.listctrl.GetItemText(i))
      ________print(selectitem)

      もっと良い書き方があるかもしれません(;´Д`)

      削除
    2. 返信ありがとうございます。ListCtrlは使い道が多くてとても役立ちます!
      難しい質問にこたえてくださりありがとうございます!

      削除