《Jython2.5》JTree〈GoF〉Command を実現する
Java プログラマーのための Python 導入ガイド〈初級/応用編〉《Jython2.5》
JTree〈GoF〉Command を実現する
《著》小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2003/05/23 ● 第2版♪2009/04/03
■ 概要
フォルダー/ファイルの階層構造を Swing/GUI を利用して「簡単に」閲覧できるツールがあると便利です。
この課題では、Swing/GUI を使って階層構造を持つ情報を提示します。 また〈GoF〉Composite/Iterator/Visitor/Command パターンを導入することで、 構造化プログラミングには必須の if/for が不要になるので、簡潔で見通しが良く、 要求仕様の変更にも柔軟に対処できる、プログラム(コード)を作成する方法を紹介します。 《Note》JPython1.1.x/Jython2.1.x 用に作成したセミナー課題を、Jython2.5 で再構成しました。
事例:コードの解説
class View(JPanel): def init_buttons(self): panel = JPanel() panel.layout = BoxLayout(panel, BoxLayout.LINE_AXIS) from TreeCommand import TextCommand self.textButton = CommandButton( label = "Text", actionPerformed = self.actionPerformed, command = TextCommand(self), ) from TreeCommand import TreeCommand self.treeButton = CommandButton( label = "Tree", actionPerformed = self.actionPerformed, command = TreeCommand(self), ) for e in [ self.textButton, self.treeButton, ]: panel.add(e) return panel def actionPerformed(self, e): e.source.command()
⇔ 承前 》何が問題だった《 のか
メソッド actionPerformed の本体では、if 文が不要になるので、簡潔で見通しの良いコードを記述できるだけでなく、要求仕様の変更にも柔軟に対処できるようになります。属性 .command は、呼び出し可能オブジェクト(TextCommand/TreeCommand)を参照するので、演算子 () に呼応して、メソッド __call__ の本体に記述したコードの断片を実行します。
■ 拡張可能なコンポーネント:
class CommandButton(JButton): pass
既存の Swing コンポーネントには、新たな属性を追加できません。そこで、子孫クラス CommandButton を用意して、新たな属性を追加できるようにします。ただし、クラスを介在させることだけに意味があるので、その本体は空 pass にします。
■ 呼び出し可能オブジェクト:__call__
メソッド __call__ は、演算子 () に呼応して、呼び出し可能オブジェクトの動作を規定します。
class Command: # Command::Command
def __init__(self, view):
self.view = view
def __call__(self):
raise NotImplementedError, self.__class__.__name__
子孫クラスでメソッド __call__ を実現しないと、実行時に例外 NotImplementedError を生成することで、プログラマーへの注意を促します。
■ 事例:テキスト表示
class TextCommand(Command): # Command::ConcreteCommand
def __call__(self):
current = self.view.currentObject
if not current: return
visitor = TextVisitor()
for e, indent in zip(current, current.indents()):
e.accept(visitor, indent)
view = JTextArea(
text = str(visitor),
font = Font("Courier", Font.PLAIN, 12),
)
from TreeView import PopWindow
win = PopWindow(
title = repr(current),
)
win.contentPane.add(JScrollPane(view))
win.open(900, 200, 300, 200)
■ 事例:ツリー表示
class TreeCommand(Command): # Command::ConcreteCommand
def __call__(self):
current = self.view.currentObject
if not current: return
root = DefaultMutableTreeNode(current)
current.accept(TreeVisitor(), root)
view = JTree(root)
from TreeView import PopWindow
win = PopWindow(
title = repr(current),
)
win.contentPane.add(JScrollPane(view))
win.open(900, 200, 300, 200)
Tips
》作業中です《
Last updated♪09/05/20