Python.use(better,Tkinter)《余録》Frame

記事一覧

Python.use(better, Tkinter)
Frame《Python3.1》

《著》森こねこ・小粒ちゃん+∞《監修》小泉ひよ子とタマゴ倶楽部
第0版♪1993/11/25 ● 第1版♪2006/10/28

■ 概要

フレームを再構成する方法を紹介します。

Tkinter によるオブジェクト指向プログラミングへの扉を開きます。
※ Tcl/Tk で作成した例題を、Tkinter で再構成しました。

部品 Frame

《余録》のコードを実行すると、2つのウィンドウが現われます。

  • 指定した値/項目に合わせて、フレームが変化します。
figure note
背景色が変化します。
枠幅が変化します。
高さが変化します。
起伏が変化します。
幅が変化します。

《余録》ソースコード〈問題篇〉:リファクタリング

《Tips》5つのメソッド command_width/command_height/command_background/command_relief/command_borderwidth の違いを捨象して、共通するコードの断片を抽出できます。

class TIPS1(object):
    def __init__(self, master, widget):
        self.master = master
        self.widget = widget
        s = "width", "height", "background", "relief", "borderwidth",
        for e in s:
            setattr(self, "var_%s"%e, StringVar(master))

    def command_width(self, e):
        s = self.var_width.get()
        self.widget.config(width=int(s))

    def command_height(self, e):
        s = self.var_height.get()
        self.widget.config(height=int(s))

    def command_background(self):
        s = self.var_background.get()
        self.widget.config(bg=s)

    def command_relief(self):
        s = self.var_relief.get()
        self.widget.config(relief=s)

    def command_borderwidth(self, e):
        s = self.var_borderwidth.get()
        self.widget.config(bd=int(s))

def createEntry(master, tips, s):
    widget = Entry(
        master=master,
        textvariable=getattr(tips, "var_%s"%s),
        width=5,
        )
    widget.bind('', getattr(tips, "command_%s"%s))
    return widget

def createMenubutton(master, tips, s, items):
    widget = Menubutton(
        master=master,
        text=s,
        )
    widget.pack()
    widget.menu = Menu(master=widget)

    for e in items:
        widget.menu.add_radiobutton(
            label=e,
            variable=getattr(tips, "var_%s"%s),
            value=e,
            command=getattr(tips, "command_%s"%s),
            )
    widget['menu'] = widget.menu
    return widget

def ex_Frame1():
    tk = Tk()
    tk.title("example")
    tk.geometry('150x80')
    frame = Frame(tk,
        width=100, height=50, bg="Yellow", relief=RIDGE, bd=5,
        )
    frame.pack()

    root = Tk()
    root.title("Frame")
    tips = TIPS1(root, frame)

    frame = Frame(root)
    frame.pack()
    widgets = {
        "width"      : createEntry(
            frame, tips, "width"),
        "height"     : createEntry(
            frame, tips, "height"),
        "borderwidth": createEntry(
            frame, tips, "borderwidth"),
        "background" : createMenubutton(
            frame, tips, "background",
            ["Cyan", "Magenta", "Yellow", "Red", "Green", "Blue",]),
        "relief"     : createMenubutton(
            frame, tips, "relief",
            [FLAT, RAISED, SUNKEN, GROOVE, RIDGE,]),
        }
    s = [(k,v) for k,v in widgets.items()]; s.sort()
    for i, (e, w) in enumerate(s):
        label = Label(frame, text="%s"%e)
        label.grid(row=i, column=0, sticky=E)
        w.grid(row=i, column=1, sticky=W)

    def quit():
        tk.destroy()
        root.destroy()
    w = Button(frame, text="QUIT", command=quit)
    w.grid(row=5, column=0, columnspan=2)

    root.config(width=200,height=150)
    root.mainloop()

《余録》ソースコード〈解決篇〉:リファクタリング

《Tips》 共通するコードの断片をもとに、2つのメソッド commandEntry/commandMenubutton を抽出しました。

class TIPS2(object):
    def commandEntry(self, e, opt):
        s = getattr(self, "var_%s"%opt).get()
        eval("self.widget.config(%s=int(%s))"%(opt, s))

    def commandMenubutton(self, opt):
        s = getattr(self, "var_%s"%opt).get()
        eval("self.widget.config(%s=%r)"%(opt, s))

def createEntry2(master, inspect, s):
    widget = Entry(
        ...
        )
    widget.bind('', lambda e: inspect.commandEntry(e, s))
    return widget

def createMenubutton2(master, inspect, s, items):
    widget = Menubutton(
        ...
        )
    widget.pack()
    widget.menu = Menu(master=widget)

    for e in items:
        widget.menu.add_radiobutton(
            ...
            command=lambda: inspect.commandMenubutton(s)
            )
    widget['menu'] = widget.menu
    return widget

def ex_Frame2():
    ...
    root = Tk()
    root.title("Frame #2")
    tips = TIPS2(root, frame)
    ...

Last updated♪2009/08/24