Software Design Lecture Notes Fall 2004 For Friday you should: 1) Do nothing! Homework 7 questions? Callbacks --------- A callback is a function provided by the programmer and invoked by the GUI, usually because the user did something. 1) simplest case: the callback is a function with no parameters def print_hello(): print 'hello' class Whatever(Gui): def setup(self): self.bu(LEFT, text='Print hello', command=print_hello) 2) most common case: the callback is a bound method with no params class Whatever(Gui): def setup(self): self.bu(LEFT, text='Hello', command=self.hello) def hello(self): self.create_text([0, 0], 'Hello') What's a bound method? Try this: class Point: def foo(): pass p = Point() print Point.foo # unbound method print p.foo # bound method 3) slightly more complicated case: the callback is a function or method that takes parameter(s). Unfortunately, the following doesn't work: def setup(self): self.bu(LEFT, text='Hello', command=self.print('hello')) def print(self, s): self.create_text([0, 0], s) Why not? Instead, you have to create a Callable object: def setup(self): callback = Callable(self.print, 'hello') self.bu(LEFT, text='Hello', command=callback) def print(self, s): self.create_text([0, 0], s) Callable is defined in World.py, but I lifted it from the Python Cookbook (with minor mods). class Callable: def __init__(self, func, *args, **kwds): # store the function and its arguments in an object self.func = func self.args = args self.kwds = kwds def __call__(self): # apply the stored function to its arguments return apply(self.func, self.args, self.kwds) Any object that defines a __call__ method can be invoked as if it were a function! Try this: class Func: def __call__(self, x): print x**2 p = Func() p(3) Binding and event-handling -------------------------- A binding is a relationship between a widget, an event and a callback. When an event (mouse-click, key press, etc.) occurs, Tk decides which widget gets the event, and which of the widget's callbacks should be invoked. Example: def setup(self): self.canvas = self.ca(...) self.canvas.bind('', self.canvas_click) The "event" in this case is the special string '' which means "a left button press". In this case we create the binding by invoking the bind method on a Canvas object. You can also bind items within a canvas. Here's an implementation of drag and drop: def circle(self): tag = self.create_circle(0, 0, 100, 'blue') self.canvas.tag_bind(tag, '', self.item_select) def item_select(self, event): print 'select', CURRENT self.canvas.bind('', self.item_drag) self.canvas.bind('', self.item_release) self.itemconfig(CURRENT, fill='red') self.set_dragx(event) def item_drag(self, event): print 'drag', CURRENT dx = event.x - self.dragx dy = event.y - self.dragy self.canvas.move(CURRENT, dx, dy) self.set_dragx(event) def set_dragx(self, event): self.dragx = event.x self.dragy = event.y def item_release(self, event): print 'release', CURRENT self.canvas.unbind('') self.canvas.unbind('') self.itemconfig(CURRENT, fill='blue')