button5 (for reference; optional)

button5.py  [download]

# Roughly like java Button5, 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="grey",
			tags="square")

		canvas.tag_bind (self._rect, '<Button-1>', 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="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 = 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 = 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/Button5/leftArrow.gif")
		if ArrowButton._rightArrow == None:
			ArrowButton._rightArrow = tkinter.PhotoImage (file="../java/Button5/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 = "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=2, 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=2, background="blue")
XButton (controlGlobal, canvas)
controlGlobal.pack (side="top")

top.mainloop()