from Gui import * class Item: """an Item object represents a canvas item. When you create a canvas item, Tkinter returns an integer 'tag' that identifies the new item. To perform an operation on the item, you invoke a method on the canvas and pass the tag as a parameter. The Item class makes this interface more object-oriented: each Item object contains a canvas and a tag. When you invoke methods on the Item, it invokes methods on its canvas. """ def __init__(self, canvas, tag): self.canvas = canvas self.tag = tag self.bind('', self.select) self.bind('', self.drag) self.bind('', self.release) def __str__(self): return 'Item' + str(self.tag) # the following are wrappers for canvas methods def bind(self, event, callback): """this method applies bindings to canvas items (not the whole canvas)""" self.canvas.tag_bind(self.tag, event, callback) def config(self, **options): """reconfigure this item with the given options""" self.canvas.itemconfig(self.tag, **options) def coords(self, *args): """get or set the canvas coordinates for this item""" return self.canvas.coords(self.tag, *args) def move(self, dx, dy): """move this item by (dx, dy) in PIXEL coordinates""" self.canvas.move(self.tag, dx, dy) def move_coord(self, i, dx, dy): """move the ith coordinate by (dx, dy) in canvas coordinates """ coords = self.coords() coords[i][0] += dx coords[i][1] += dy self.coords(coords) def replace_coord(self, i, coord): """replace the ith coordinate with the given canvas coordinate""" coords = self.coords() coords[i] = coord self.coords(coords) # the following event handlers take an event object as a parameter def select(self, event): print 'Item.select', self self.config(fill='red') self.set_drag(event) def drag(self, event): """move this item using the pixel coordinates in the event object.""" # see how far we have moved dx, dy = self.sub_drag(event, self.drag) # save the current drag coordinates self.set_drag(event) # move the item # NOTE: the reason we have to negate dy is to translate # from pixel coordinates to canvas coordinates, # but this is a terrible hack, because it assumes that # the only transform in effect is a CanvasTransform. self.move(dx, -dy) return dx, dy def release(self, event): print 'Item.release', self self.config(fill='blue') # the following methods are for dealing with events and drag # coordinates def get_drag(self, event): """get the drag coordinates from this event and translate them into canvas coordinates""" x, y = self.canvas.trans([event.x, event.y]) return x, y def set_drag(self, event): """store the current drag coordinates""" self.drag = self.get_drag(event) def sub_drag(self, event, d2): """subtract d2 from the drag coordinates in event""" d1 = self.get_drag(event) return d1[0] - d2[0], d1[1] - d2[1] class Hello(Gui): def __init__(self): Gui.__init__(self) self.ca_width = 400 self.ca_height = 400 self.setup() def setup(self): # frame 1 self.fr(TOP) self.canvas = self.ca(width=self.ca_width, height=self.ca_height, bg='white') self.canvas.bind('', self.click) self.endfr() # frame 2 self.fr(TOP, fill=BOTH, expand=1) self.fr() self.bu(LEFT, text='Hello', command=self.hello) self.bu(LEFT, text='Circle', command=self.circle) self.bu(LEFT, text='Quit', command=self.quit) self.endfr() self.endfr() def hello(self): font = ('Helvetica', 36) tag = self.canvas.text([0, 0], 'Hello', font=font, fill='blue') item = Item(self.canvas, tag) def circle(self): tag = self.canvas.circle(0, 0, 100, 'blue') item = Item(self.canvas, tag) def click(self, event): """this event handler gets invoked when the user clicks on the canvas.""" print 'Hello.click', event.type, event.num, event.x, event.y if __name__ == '__main__': h = Hello() h.mainloop()