Python.use(better, Tkinter=”GoF”) # Strategy
‖記事一覧‖
Python.use(better, Tkinter=”GoF") # Python で学ぶ デザインパターンの世界
《著》森こねこ・小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
α版♪1993/11/25 ● β版♪1995/11/22
概要
Tkinter アプリケーションとして、Python で実現した事例を紹介します。
Tkinter によるオブジェクト指向プログラミングへの扉を開きます。
※ Tcl/Tk で作成した例題を、Tkinter で再構成しました。
事例
次のコードを実行すると、ウィンドウが現われます。
>>> strategy()
## ---------------------------------------- from tkinter import * from tkinter.filedialog import FileDialog ## ---------------------------------------- Observer::Subject class Subject(object): def attach_(self, observer): pass def detach_(self, observer): pass def notify_(self): pass ## ---------------------------------------- Observer::Observer class Observer(object): def update_(self): pass ## ---------------------------------------- class ColorSubject(Subject): def __init__(self): self.value = StringVar() self.observers = [] def background(self, value=None): if value is None: return self.value.get() else: self.value.set(value) self.notify_() ## ---------------------------------------- def attach_(self, observer): self.observers.append(observer) def notify_(self): for e in self.observers: e.update_() ## ---------------------------------------- Observer::ConcreteObserver class ConcreteObserver(Observer): def _subject(self, subject): self.subject = subject self.subject.attach_(self) ## ---------------------------------------- def update_(self): bg = self.subject.value.get() self.canvas.config(bg=bg) ## ---------------------------------------- class TIPS(ConcreteObserver): def __init__(self, master): self._subject(ColorSubject()) self.context = Context(self.subject) self.master = master self.canvas = self.create_Canvas(master) self.create_Menubutton(master) self.create_CommandButton(master) ## ---------------------------------------- def create_Canvas(self, master): widget = Canvas( master=master, width=100, height=100, relief=RIDGE, borderwidth=5, ) widget.pack(side=LEFT) return widget def create_Menubutton(self, master): widget = Menubutton( master=master, text='File', ) widget.pack(side=TOP) menu = Menu(widget) widget['menu'] = menu for text, command in [ ("Open...", self.fileCommand), ("Scale" , self.openScale ), ("Entry" , self.openEntry ), ("Exit" , self.exitCommand), ]: CommandMenu( menu=menu, text=text, command=command, ) def create_CommandButton(self, master): frame = Frame(master) frame.pack(side=TOP) s = "aliceblue", "beige", "lavender", for e in s: widget = CommandButton( master=frame, text=e, variable=self.subject.value, command=self.notify_, ) widget.pack(anchor=W) ## ---------------------------------------- def fileCommand(self): dir_or_file = "./_flags" s = FileDialog(self.master).go(dir_or_file) self.image = PhotoImage(file=s) s = s.split("/")[-1] text = s.split(".")[0] dx = self.master["padx"] dx = int(str(dx)) x, y, dy = 50+dx, 80, 8 self.canvas.create_image( x, y , anchor=S, image=self.image) self.canvas.create_text( x, y+dy, anchor=N, text=text) def openScale(self): self.context.setScaleStrategy() self.context.open_() def openEntry(self): self.context.setEntryStrategy() self.context.open_() def exitCommand(self): self.master.destroy() ## ---------------------------------------- def notify_(self): for e in self.subject.observers: e.update_() ## ---------------------------------------- Strategy::Context class Context(object): def __init__(self, subject): self.subject = subject ## ---------------------------------------- def setScaleStrategy(self): self.strategy = ScaleStrategy(self.subject) def setEntryStrategy(self): self.strategy = EntryStrategy(self.subject) def open_(self): self.strategy.create_() ## ---------------------------------------- Strategy::Strategy class Strategy(object): def create_(self): pass ## ---------------------------------------- Strategy::ConcreteStrategy class ConcreteStrategy(Strategy): items = "red", "green", "blue", def __init__(self, subject): self._subject(subject) self.values = self.create_values() self.top = self.create_Toplevel() def _subject(self, subject): self.subject = subject self.subject.attach_(self) def create_values(self): return dict*1 for e in self.items) def create_Toplevel(self): widget = Toplevel() widget.title("Entry") widget.config(padx=50, pady=4) return widget ## ---------------------------------------- def update_(self): bg = self.subject.background() rgb = [e>>8 for e in self.top.winfo_rgb(bg)] for key, value in zip(self.items, rgb): self[key] = value ## ---------------------------------------- def __getitem__(self, key): return self.values[key].get() def __setitem__(self, key, value): self.values[key].set(value) def __call__(self, event): value = [self[e] for e in self.items] bg = ("#"+"%02X"*len(value))%tuple(value) self.subject.background(value=bg) ## ---------------------------------------- Observer::ConcreteSubject class ScaleStrategy(ConcreteStrategy): def create_(self): self.scales = {} for e in self.items: widget = Scale( master=self.top, from_=0, to=255, orient=HORIZONTAL, length=255, variable=self.values[e], command=self, ) widget.pack() self.scales[e] = widget ## ---------------------------------------- Observer::ConcreteSubject class EntryStrategy(ConcreteStrategy): def create_(self): for e in self.items: widget = Entry( master=self.top, width=5, textvariable=self.values[e], ) widget.bind('', self) widget.pack(pady=2) ## ---------------------------------------- class CommandHolder(object): pass class CommandButton(CommandHolder, Radiobutton): def __init__(self, master, text, variable, command): super().__init__( master=master, text=text, value=text, variable=variable, command=command, ) class CommandMenu(CommandHolder): def __init__(self, menu, text, command): menu.add_radiobutton( label=text, command=command, ) ## ======================================== def strategy(): root = Tk() root.title("strategy") root.config(padx=8, pady=4) TIPS(master=root) root.mainloop()
↑TOP
関連記事
- INDEX《Tkinter》
- Let’s GoForward - GoF を反面教師に
- C# Design Patterns 22. The Command Pattern.
Last updated♪2009/09/20
*1:e,IntVar(