#!/usr/bin/python from Tkinter import * # turning on debugging changes the behavior of Gui.fr so # that the nested frame structure is apparent debug = 0 # Gui provides wrappers for many of the methods in the Tk # class; also, it keeps track of the current frame so that # you can create new widgets without naming the parent frame # explicitly. class Gui(Tk): def __init__(self): Tk.__init__(self) self.frame = self # the current frame self.frames = [] # the stack of nested frames # frame def fr(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): # save the current frame, then create the new one self.frames.append(self.frame) if debug: options['bd'] = 5 options['relief'] = RIDGE self.frame = self.widget(Frame, side, fill, expand, anchor, **options) return self.frame # end frame def endfr(self): self.frame = self.frames.pop() # top level window def tl(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): # push the current frame, then create the new one self.frames.append(self.frame) self.frame = Toplevel(options) return self.frame # canvas def ca(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): return self.widget(Canvas, side, fill, expand, anchor, **options) # label def la(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): return self.widget(Label, side, fill, expand, anchor, **options) # button def bu(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): return self.widget(Button, side, fill, expand, anchor, **options) # menu button def mb(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): mb = self.widget(Menubutton, side, fill, expand, anchor, **options) mb.menu = Menu(mb, relief=SUNKEN) mb['menu'] = mb.menu return mb # menu item def mi(self, mb, label='', **options): mb.menu.add_command(label=label, **options) # entry def en(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, text='', **options): en = self.widget(Entry, side, fill, expand, anchor, **options) en.insert(0, text) return en # text entry def te(self, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): return self.widget(Text, side, fill, expand, anchor, **options) # this is the mother of all widget constructors. the constructor # argument is the function object that will be called to build # the new widget def widget(self, constructor, side=TOP, fill=NONE, expand=0, anchor=CENTER, **options): widget = constructor(self.frame, options) widget.pack(side=side, fill=fill, expand=expand, anchor=anchor) return widget # the following are wrappers on the tk canvas items def create_circle(self, x, y, r, fill='', **options): options['fill'] = fill coords = self.trans([[x-r, y-r], [x+r, y+r]]) tag = self.canvas.create_oval(coords, options) return tag; def create_oval(self, coords, fill='', **options): options['fill'] = fill return self.canvas.create_oval(self.trans(coords), options) def create_rectangle(self, coords, fill='', **options): options['fill'] = fill return self.canvas.create_rectangle(self.trans(coords), options) def create_line(self, coords, fill='black', **options): options['fill'] = fill tag = self.canvas.create_line(self.trans(coords), options) return tag; def create_polygon(self, coords, fill='', **options): options['fill'] = fill return self.canvas.create_polygon(self.trans(coords), options) def create_text(self, coord, text='', fill='black', **options): options['text'] = text options['fill'] = fill return self.canvas.create_text(self.trans([coord]), options) def create_image(self, coord, image, **options): options['image'] = image return self.canvas.create_image(self.trans([coord]), options) def itemconfig(self, tag, **options): self.canvas.itemconfig(tag, options) def itemcget(self, tag, option): return self.canvas.itemcget(tag, option) def delete_item(self, tag): self.canvas.delete(tag) def move_item(self, tag, dx, dy): self.canvas.move(tag, dx, dy) def print_canvas(self, filename='gui.eps'): ps = self.canvas.postscript() fp = open(filename, 'w') fp.write(ps) fp.close() def trans(self, coords): for trans in self.transforms: coords = trans.trans_list(coords) return coords class Callback: # see Python Cookbook 9.1, page 302 def __init__(self, callback, *args, **kwds): self.callback = callback self.args = args self.kwds = kwds def __call__(self): return apply(self.callback, self.args, self.kwds) class Transform: def trans_list(self, points): return [self.trans(p) for p in points] def invert_list(self, points): return [self.invert(p) for p in points] class CanvasTransform(Transform): def __init__(self, width, height, xscale=1, yscale=1): self.width = width self.height = height self.xscale = xscale self.yscale = yscale def trans(self, p): x = p[0] * self.xscale + self.width/2 y = -p[1] * self.yscale + self.height/2 return [x, y]