2016-06-04

【備忘録】CustomTreeCtrl とポップアップメニュー ─ wxPython

JavaFX で作っていたプログラムで、リソース不足 (OutOfMemoryError) に悩まされているため、結局同じことになるかもしれないと思いつつも、軽快に GUI が動く wxPython にプログラムを移植しています。python のプログラミングに不慣れなためハマった個所を備忘録としてブログ用のサンプルに書き換えて残しています。

今回は CustomTreeCtrl です。参考文献 [1] を参考にして、JavaFX の時と同じようなサンプルを作ってみました [2]。ポップアップメニューは、ツリーの末端のアイテムのみ表示するために、判定用に wx.TreeItemData() を利用してアイテムに値を持たせています。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Beta)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-5.0.0-1.fc24.x86_64
#!/usr/bin/env python
# -*- coding: utf-8 -*- 

import wx
import wx.lib.agw.customtreectrl as CT

ID_TREE = wx.NewId()

class MyTree(CT.CustomTreeCtrl):
    def __init__(self, parent):
        CT.CustomTreeCtrl.__init__(self, parent, wx.ID_ANY, agwStyle=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)

        # image list
        il = wx.ImageList(32, 32)
        CAROT = il.AddIcon(wx.Icon("image/carot.png", wx.BITMAP_TYPE_PNG))
        EGGPLANT = il.AddIcon(wx.Icon("image/eggplant.png", wx.BITMAP_TYPE_PNG))
        TOMATO = il.AddIcon(wx.Icon("image/tomato.png", wx.BITMAP_TYPE_PNG))
        APPLE = il.AddIcon(wx.Icon("image/apple.png", wx.BITMAP_TYPE_PNG))
        GRAPE = il.AddIcon(wx.Icon("image/grape.png", wx.BITMAP_TYPE_PNG))
        BANANA = il.AddIcon(wx.Icon("image/banana.png", wx.BITMAP_TYPE_PNG))
        self.SetImageList(il)

        root = self.AddRoot(u"食べ物")
        vegetable = self.AppendItem(root, u"野菜")
        fruit = self.AppendItem(root, u"果物")

        leafData = wx.TreeItemData("leaf")

        carot = self.AppendItem(vegetable, u"にんじん")
        self.SetItemImage(carot, CAROT)
        self.SetPyData(carot, leafData)

        eggplant = self.AppendItem(vegetable, u"なす")
        self.SetItemImage(eggplant, EGGPLANT)
        self.SetPyData(eggplant, leafData)

        tomato = self.AppendItem(vegetable, u"とまと")
        self.SetItemImage(tomato, TOMATO)
        self.SetPyData(tomato, leafData)

        apple = self.AppendItem(fruit, u"りんご")
        self.SetItemImage(apple, APPLE)
        self.SetPyData(apple, leafData)

        grape = self.AppendItem(fruit, u"ぶどう")
        self.SetItemImage(grape, GRAPE)
        self.SetPyData(grape, leafData)

        banana = self.AppendItem(fruit, u"ばなな")
        self.SetItemImage(banana, BANANA)
        self.SetPyData(banana, leafData)
        
        self.ExpandAll()


class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size=wx.Size(300, 400))
        self.CreateStatusBar()
        self.createMenu()

        self.tree = MyTree(self)
        self.tree.Bind(wx.EVT_CONTEXT_MENU, self.showPopupMenu)

        layout = wx.BoxSizer(wx.VERTICAL)
        layout.Add(self.tree, proportion=1, flag=wx.GROW)
        self.SetSizer(layout)
        self.Centre()
        
    def createMenu(self):
        self.menu = wx.Menu()
        item_tree = wx.MenuItem(self.menu, ID_TREE, u"処理")
        self.menu.AppendItem(item_tree)
        self.Bind(wx.EVT_MENU, self.OnCapital, id=ID_TREE)

    def showPopupMenu(self, evt):
        item_id = self.tree.GetSelection()
        item_data = self.tree.GetItemPyData(item_id)
        if item_data != None:
            if item_data.GetData() == "leaf":
                position = self.ScreenToClient(wx.GetMousePosition())
                self.PopupMenu(self.menu, position)

    def OnCapital(self, event):
        itemId = self.tree.GetSelection()
        itemText = self.tree.GetItemText(itemId)
        self.SetStatusText(u"「" + itemText + u"」が選択されました。")


class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, wx.ID_ANY, "MyTree")
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

実行例を以下に示しました。

 

参考サイト

  1. customtreectrl — wxPython (Phoenix) 3.0.3 documentation
  2. bitWalk's: JavaFX: TreeView と ContextMenu (2)

 

ブログランキング・にほんブログ村へ
にほんブログ村

0 件のコメント: