I have image of a kitchen table on tkinter canvas. A foreground object image (e.g., a cup) is inserted on top of table image. Cup image has alpha channel to remove its local background so cup appears to be sitting on table. Both background image and foreground image were added to canvas in standard way using:
canvas.create_image()
Everything described above works.
Goal is this: place circle around cup image when mouse is over cup (so user knows item can be picked up) then allow user to click on cup image and drag it to new location on table (i.e., canvas).
I tried binding mouse down event to circle (see code below). For this, I followed general example linked below; however, it didn't work in my case.
python tkinter canvas when rectangle clicked
Below is simplified code to reproduce problem. Code puts circle on canvas and defines four related callbacks. Three are bound to circle; one to canvas. Expectation is that all four callbacks should work. Reality is callbacks bound to circle via tags="click_zone" don't work while callback bound to canvas works.
import cv2
from tkinter import Tk, Canvas
from PIL import ImageTk, Image
import time
class ClickZone:
def __init__(self, _canvas, _bbox):
self.click_zone = _canvas.create_oval(_bbox, tags=("click zone"))
_canvas.tag_bind("click zone", '<Enter>', self.on_enter)
_canvas.tag_bind("click zone", '<Leave>', self.on_leave)
_canvas.tag_bind("click zone", '<ButtonPress-1>', self.pick_up_object)
_canvas.bind("<ButtonRelease-1>", self.drop_object)
def drop_object(self, event):
print("Drop")
def pick_up_object(self, event):
print("Pick up")
def on_enter(self, event):
print("Enter")
def on_leave(self, event):
print("Leave")
root = Tk()
canvas = Canvas(root, width=800, height=600)
canvas.grid()
# Center of inserted object image
x_center_fg_object = 400
y_center_fg_object = 300
# Diameter of smallest circle fully enclosing inserted object image
fg_object_click_zone_radius = 250
# Bounding box around click zone circle
x0 = x_center_fg_object - fg_object_click_zone_radius
y0 = y_center_fg_object - fg_object_click_zone_radius
x1 = x_center_fg_object + fg_object_click_zone_radius
y1 = y_center_fg_object + fg_object_click_zone_radius
bbox = (x0, y0, x1, y1)
fg_object_click_zone = ClickZone(canvas, bbox)
root.mainloop()
Ultimately, I would like to bind pick-up mouse event directly to image instead of to the circle; however, I never found an example online where someone successfully binds mouse event to image on canvas.