Python.use(better, Tkinter=”GoF”) # Visitor

記事一覧 Python.use(better)《Python3.1》

Visitor

《著》森こねこ・小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
α版♪1993/11/25 ● β版♪1995/11/22 ● 第1版♪2003/05/23

概要

Tkinter/Python によるオブジェクト指向プログラミングへの扉を開きます。
※ 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


関連記事

Last updated♪2009/09/23