Tkinter bind widgets below a rectangle widget to a mouse event
<p>I hope I am explaining the problem correctly. 
My example below is able to move two images defined on a canvas. The problem is that I want a rectangle, also defined on the canvas, on top of the images. When I do that using .tag_raise, the event triggered by mouse drag is triggered by the rectangle, not the images. </p>

<p>I tried using bing_class but that did not work. I tried to define a separate canvas for the rectangle but it has to overlay the main canvas and I got stuck.</p>

<p>How to keep the rectangle on top but bind the images to my mouse drag event?</p>

<pre><code>import Tkinter as tk # for Python2
import PIL.Image, PIL.ImageTk

win = tk.Tk()
canvas = tk.Canvas(win, height = 500, width = 500)

#Create a rectangle with stipples on top of the images
rectangle = canvas.create_rectangle(0, 0, 400, 300, fill = "gray", stipple = "gray12")

#Create two images
SPRITE = PIL.Image.open("image.jpg")
imagePIL = SPRITE.resize((100, 100))
imagePI = PIL.ImageTk.PhotoImage(imagePIL)
image1 = canvas.create_image(100, 100, image = imagePI, tags = "image")
image2 = canvas.create_image(200, 200, image = imagePI, tags = "image")

#Callback
# Here I select image1 or image2 depending on where I click, and
# drag them on the canvas. The problem is when I put the rectangle
# on top using tag_raise (see below).
def callback(event):
    id = canvas.find_withtag(tk.CURRENT)
    canvas.coords(id, (event.x, event.y))

#Binding
canvas.bind("&lt;B1-Motion&gt;", callback)
#Place the rectangle on top of all
canvas.pack()

# This is the problem. I want to have the rectangle on top and be able to use the callback
#canvas.tag_raise(rectangle)

canvas.mainloop()
</code></pre>

<p><strong>SOLUTION:</strong> I enhanced Nehal's answer with the following code. His answer had a glitch, by which images could be switched. In my enhancement I solve it by storing a lock for each image so that, while dragging an image around on the canvas, the same image is dragged. When I move e.g. image1 over image2 I notice that image1 does not completely move over image2, which is fine for me. </p>

<pre><code>import Tkinter as tk # for Python2
import PIL.Image, PIL.ImageTk

win = tk.Tk()
canvas = tk.Canvas(win, height = 500, width = 500)

#Create a rectangle with stipples on top of the images
rectangle = canvas.create_rectangle(0, 0, 400, 300, fill = "gray", stipple = "gray12")

#Create two images
SPRITE = PIL.Image.open("image.jpg")
imagePIL = SPRITE.resize((100, 100))
imagePI = PIL.ImageTk.PhotoImage(imagePIL)
image1 = canvas.create_image(100, 100, image = imagePI, tags = "image")
image2 = canvas.create_image(200, 200, image = imagePI, tags = "image")
images = [image1, image2]
locks = [True, True]

def getImage(x, y):
    for image in images:
        curr_x, curr_y = canvas.coords(image)
        x1 = curr_x - imagePI.width()/2
        x2 = curr_x + imagePI.width()/2
        y1 = curr_y - imagePI.height()/2
        y2 = curr_y + imagePI.height()/2
        if (x1 &lt;= x &lt;= x2) and (y1 &lt;= y &lt;= y2):
            return image
#Callback
# Here I select image1 or image2 depending on where I click, and
# drag them on the canvas.
def callback(event):
    id  = getImage(event.x, event.y)
    if id:
        if locks[images.index(id)] is False: #Hold on to the image on which I originally clicked
            canvas.coords(id, (event.x, event.y))

def mouseClick(event):
    id  = getImage(event.x, event.y)
    if id:
        locks[images.index(id)] = False
    print(locks)

def mouseRelease(event):
    id  = getImage(event.x, event.y)
    if id:
        locks[images.index(id)] = True
    print(locks)
#Binding
canvas.bind("&lt;ButtonPress-1&gt;", mouseClick)      #unlock the image to move it
canvas.bind("&lt;ButtonRelease-1&gt;", mouseRelease)  #lock the image
canvas.bind("&lt;B1-Motion&gt;", callback)
#Place the rectangle on top of all
canvas.pack()

# This was the original problem
canvas.tag_raise(rectangle)

canvas.mainloop()
</code></pre>

<p>I don't know a <code>tkinter</code> specific way to do this, however, you can try to get the coordinates of the closest image and play with them. Like this:</p>

<pre><code>import Tkinter as tk # for Python2
import PIL.Image, PIL.ImageTk

win = tk.Tk()
canvas = tk.Canvas(win, height = 500, width = 500)

#Create a rectangle with stipples on top of the images
rectangle = canvas.create_rectangle(0, 0, 400, 300, fill = "gray", stipple = "gray12")

#Create two images
SPRITE = PIL.Image.open("image.jpg")
imagePIL = SPRITE.resize((100, 100))
imagePI = PIL.ImageTk.PhotoImage(imagePIL)
image1 = canvas.create_image(100, 100, image = imagePI, tags = "image")
image2 = canvas.create_image(200, 200, image = imagePI, tags = "image")
images = [image1, image2]

def getImage(x, y): 
    for image in images:
        curr_x, curr_y = canvas.coords(image)
        x1 = curr_x - imagePI.width()/2
        x2 = curr_x + imagePI.width()/2
        y1 = curr_y - imagePI.height()/2
        y2 = curr_y + imagePI.height()/2
        if (x1 &lt;= x &lt;= x2) and (y1 &lt;= y &lt;= y2):
            return image
#Callback
# Here I select image1 or image2 depending on where I click, and
# drag them on the canvas. The problem is when I put the rectangle
# on top using tag_raise (see below).
def callback(event):
    id  = getImage(event.x, event.y)
    if id: 
        canvas.coords(id, (event.x, event.y))

#Binding
canvas.bind("&lt;B1-Motion&gt;", callback)
#Place the rectangle on top of all
canvas.pack()

# This is the problem. I want to have the rectangle on top and be able to use the callback
canvas.tag_raise(rectangle)

canvas.mainloop()
</code></pre>

<p><a href="http://i.stack.imgur.com/H1GeH.gif" rel="nofollow"><img src="http://i.stack.imgur.com/H1GeH.gif" alt="enter image description here"></a></p>

python user-interface canvas tkinter tkinter-canvas