# Roughly like java ButtonApp4, but exploiting retained canvas items # Weird import for compatibility across Python 2 and Python 3 try: import tkinter except ImportError: import Tkinter as tkinter # # CLASS SQUARE # class Square (): # Class var _squareCount = 0 def __init__(self, canvas): # Class var Square._squareCount += 1 # Stash arg as ivar self._canvas = canvas # Make our rectangle object self._rect = canvas.create_rectangle ( 30 * Square._squareCount, 20 * Square._squareCount, 30 * Square._squareCount + 50, 20 * Square._squareCount + 50, fill="light grey", tags="square") canvas.tag_bind (self._rect, '', self._onclick) # Mouse callback for an individual square def _onclick (self, event): # Unselect and unfill previously selected square if any self._canvas.itemconfigure ("selected", fill="light grey") self._canvas.dtag ("square", "selected") # Then select and fill me self._canvas.addtag_withtag ("selected", self._rect) self._canvas.itemconfigure (self._rect, fill="black") # # BUTTON SUPERCLASSES # # Our superclass for all our buttons class MyButton (tkinter.Button): # Simulate an enum type for which action to take, using classvars LEFT, RIGHT, BIGGER, SMALLER = list(range(4)) def __init__(self, parent, canvas, action): tkinter.Button.__init__ (self, parent) self._canvas = canvas self["command"] = self._myCallback self.pack(side="left") self._action = action def _myCallback (self): x0, y0, x1, y1 = self._canvas.coords ("selected") if self._action==MyButton.LEFT: x0 -= 10 x1 -= 10 elif self._action==MyButton.RIGHT: x0 += 10 x1 += 10 elif self._action==MyButton.BIGGER: x1 += 10 y1 += 10 elif self._action==MyButton.SMALLER: x1 -= 10 y1 -= 10 self._canvas.coords ("selected", x0, y0, x1, y1) class TextButton (MyButton): def __init__(self, parent, canvas, action, label): MyButton.__init__ (self, parent, canvas, action) self["text"] = label class ArrowButton (MyButton): # Enum for which arrow to draw LEFTARROW, RIGHTARROW = list(range(2)) # Keep these around, if they go out of scope our buttons lose the images _leftArrow = None _rightArrow = None def __init__(self, parent, canvas, action, direction): MyButton.__init__ (self, parent, canvas, action) # Load these up (just once) if ArrowButton._leftArrow == None: ArrowButton._leftArrow = tkinter.PhotoImage (file="../java/ButtonApp4/leftArrow.gif") if ArrowButton._rightArrow == None: ArrowButton._rightArrow = tkinter.PhotoImage (file="../java/ButtonApp4/rightArrow.gif") if direction==ArrowButton.LEFTARROW: self["image"] = ArrowButton._leftArrow else: self["image"] = ArrowButton._rightArrow # # BUTTON CLASSES # class LeftButton (ArrowButton): def __init__(self, parent, canvas): ArrowButton.__init__ (self, parent, canvas, MyButton.LEFT, ArrowButton.LEFTARROW) class RightButton (ArrowButton): def __init__(self, parent, canvas): ArrowButton.__init__ (self, parent, canvas, MyButton.RIGHT, ArrowButton.RIGHTARROW) class BiggerButton (TextButton): def __init__(self, parent, canvas): TextButton.__init__ (self, parent, canvas, MyButton.BIGGER, "Bigger") class SmallerButton (TextButton): def __init__(self, parent, canvas): TextButton.__init__ (self, parent, canvas, MyButton.SMALLER, "Smaller") class XButton (TextButton): def __init__(self, parent, canvas): TextButton.__init__ (self, parent, canvas, None, "X") def _myCallback (self): if self._canvas.itemcget ("x", "state") == "hidden": self._canvas.itemconfigure ("x", state="normal") else: self._canvas.itemconfigure ("x", state="hidden") # # MAIN PROGRAM # top = tkinter.Tk() # Canvas, its former constructor code just all goes here canvas = tkinter.Canvas (top, height=400, width=400, background = "light grey") canvas.pack (fill="both", expand=1) # Model, ditto, because it has little to do, no data to remember # Create the "X", initially hidden canvas.create_line (0, 0, 400, 400, state="hidden", tag="x") canvas.create_line (400, 0, 0, 400, state="hidden", tag="x") # Create the objects for i in range(5): Square (canvas) # controlSingle and its buttons controlSingle = tkinter.Frame (top, borderwidth=3, background="blue") LeftButton (controlSingle, canvas) RightButton (controlSingle, canvas) BiggerButton (controlSingle, canvas) SmallerButton (controlSingle, canvas) controlSingle.pack (side="top") # controlGlobal and its button controlGlobal = tkinter.Frame (top, borderwidth=3, background="blue") XButton (controlGlobal, canvas) controlGlobal.pack (side="top") top.mainloop()