Python.use(better, Tkinter=”GoF”) # Visitor
‖記事一覧‖
Python.use(better, Tkinter=”GoF") # Python で学ぶ デザインパターンの世界
《著》森こねこ・小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
α版♪1993/11/25 ● β版♪1995/11/22 ● 第1版♪2003/05/23
概要
Tkinter アプリケーションとして、Python で実現した事例を紹介します。
Tkinter によるオブジェクト指向プログラミングへの扉を開きます。
※ Tcl/Tk で作成した例題を、Tkinter で再構成しました。
事例:step 4
次のコードを実行すると、ウィンドウが現われます。
>>> tips()
## ---------------------------------------- from tkinter import * ## ---------------------------------------- from os import listdir from os.path import join, isdir from functools import reduce from os.path import getsize, getatime, getmtime, getctime from time import ctime ## ---------------------------------------- Composite::Component class Component(object): def __init__(self, path, item): self.path = path self.item = item ## ---------------------------------------- Iterator::Iterator def __iter__(self): pass ## ---------------------------------------- def add_(self, component): pass ## ---------------------------------------- def print(self): for i, e in zip(self.indents(), self.items()): print("%s%s"%("+ "*i, e)) ## ---------------------------------------- Command::Receiver def createPanel(self): top = Toplevel() top.title(self.item) top.config(padx=16, pady=4) current = join(self.path, self.item) frame = Frame(master=top) frame.pack() item = "getsize" w = Label(master=frame, text=item) w.pack(side=LEFT) w = Entry(master=frame, width=10) w.pack(side=LEFT) w.insert(END, getsize(current)) frame = Frame(master=top) frame.pack() items = "getatime", "getmtime", "getctime", for i, e in enumerate(items): w = Label(master=frame, text=e) w.grid(row=i, column=0, sticky=E) w = Entry(master=frame, width=22) w.grid(row=i, column=1, sticky=W) w.insert(END, eval("ctime(%s('%s'))"%(e, current))) ## ---------------------------------------- Visitor::Element def accept_(self, visitor, arg=0): eval("visitor.visit%s_(self, arg)"%self.__class__.__name__) ## ---------------------------------------- Composite::Leaf class Leaf(Component): ## ---------------------------------------- Iterator::ConcreteIterator def __iter__(self): return self def __repr__(self): return "#%r"%self.item def __str__(self): return "%s"%self.item ## ---------------------------------------- def items(self): return [self.item] def indents(self, level): return [level] def dirs(self): return [False] def nodes(self): return [self] ## ---------------------------------------- Composite::Composite class Composite(Component): def __init__(self, path, item): super().__init__(path, item) self.children = ## ---------------------------------------- Iterator::ConcreteIterator def __iter__(self): for e in self.children: yield e def __repr__(self): return "%s(#%s: [%s])"%( self.__class__.__name__, self.item, ",".join([str(e) for e in self]), ) def __str__(self): return "\n".join([self.item]+[str(e) for e in self]) ## ---------------------------------------- def items(self): return reduce(lambda s,e: s+e.items(), self, [self.item]) def indents(self, level=0): return reduce(lambda s,e: s+e.indents(level+1), self, [level]) def dirs(self): return reduce(lambda s,e: s+e.dirs(), self, [True]) def nodes(self): return reduce(lambda s,e: s+e.nodes(), self, [self]) ## ---------------------------------------- def add_(self, component): self.children.append(component) ## ---------------------------------------- Composite::Client class TIPS(object): # Client, Aggregate def __init__(self, master, path): self.tree = Composite(path, self.tail(path)) self.dirImage = PhotoImage(file="_image/folder.gif") self.fileImage = PhotoImage(file="_image/file.gif") self.master = master self.path = path def tail(self, path): return path.split("/")[-1] ## ---------------------------------------- def createNodes(self): self._createNodes(self.tree, self.path) def _createNodes(self, parent, path, indent=0): for e in listdir(path): current = join(path, e) if isdir(current): component = Composite(path, e) parent.add_(component) self._createNodes(component, current, indent+1) else: component = Leaf(path, e) parent.add_(component) ## ---------------------------------------- Command::Invoker class Invoker(object): pass class ButtonInvoker(Invoker, Button): def __init__(self, master, image, receiver): super().__init__( master=master, image=image, command=PanelCommand(receiver), ) ## ---------------------------------------- Command::Command class Command(object): def __init__(self, receiver): self.receiver = receiver def __call__(self): pass ## ---------------------------------------- Command::ConcreteCommand class PanelCommand(Command): def __call__(self): self.receiver.createPanel() ## ---------------------------------------- class TreeWidget(object): def __init__(self, tree=None, path=None, **keys): self.items = self.top = self.create_Toplevel(tree=tree) self.widget = self.create_widget(master=self.top, tree=tree) def create_Toplevel(self, tree): widget = Toplevel() s = tree.path.split("/") title = "%s: %s"%(s[-1],"/".join(s[:-1])) widget.title(title) widget.config(padx=16, pady=4) return widget ## ---------------------------------------- class ButtonTreeWidget(TreeWidget): def __init__(self, tree=None, path=None, **keys): self.dirImage = PhotoImage(file="_image/folder.gif") self.fileImage = PhotoImage(file="_image/file.gif") super().__init__(tree, path) tree.accept_(TreeVisitor(self)) def create_widget(self, master, tree): widget = Frame(master=master) widget.pack() return widget def append(self, master, tab, image, node): bg = "aliceblue" # "aliceblue,yellow,cyan" font = "courier 12" side = LEFT frame = Frame(master) frame.config(bg=bg) frame.pack(anchor=W) Label(frame, text=tab , font=font ).pack(side=side) ButtonInvoker(frame, image, receiver=node).pack(side=side) Label(frame, text=node.item, font=font ).pack(side=side) ## ---------------------------------------- class TextTreeWidget(TreeWidget): def __init__(self, tree=None, path=None, **keys): super().__init__(tree, path) tree.accept_(TextVisitor(self)) def create_widget(self, master, tree): widget = Text(master=master, width=52) widget.pack() widget.insert(END, "%s\n"%tree.path) return widget def append(self, string): self.widget.insert(END, string) ## ---------------------------------------- Visitor::Visitor class Visitor(object): def visitLeaf_(self, *args): pass def visitComposite_(self, *args): pass ## ---------------------------------------- Visitor::ConcreteVisitor class ConcreteVisitor(Visitor): def __init__(self, client): self.client = client class TreeVisitor(ConcreteVisitor): def visitLeaf_(self, node, indent): tab1 = " " tab2 = " . " self.client.append( master=self.client.widget, tab=tab1*indent+tab2, image=self.client.fileImage, node=node, ) pass def visitComposite_(self, node, indent): tab1 = " " tab2 = " - " self.client.append( master=self.client.widget, tab=tab1*indent+tab2, image=self.client.dirImage, node=node, ) for e in node: e.accept_(TreeVisitor(self.client), indent+1) class TextVisitor(ConcreteVisitor): def visitLeaf_(self, node, indent): self.client.append(self._item(indent, ". ", node)) def visitComposite_(self, node, indent): self.client.append(self._item(indent, "- ", node)) for e in node: e.accept_(TextVisitor(self.client), indent+1) def _item(self, indent, s, node): return "\n"+"| "*indent + s + node.item ## ---------------------------------------- def tips(): root = Tk() root.title("Visitor") root.geometry("150x50") path = "Python-3.0/Mac/BuildScript" tips = TIPS(root, path) tips.createNodes() tree = TextTreeWidget(tree=tips.tree) tree = ButtonTreeWidget(tree=tips.tree) root.mainloop()
↑TOP
関連記事
- INDEX《Tkinter》
- Let’s GoForward - GoF を反面教師に
- C# Design Patterns 31. The Visitor Pattern.
Last updated♪2009/09/23