Reputation: 23
I am working on an application that requires repositioning of canvas items. I developed the following grabbablePoint class but new points are not CURRENT unless I move the mouse off and then back over the point.
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
class grabbablePoint:
def __init__(self, canvas, x, y, r):
if not(canvas.find_withtag(tk.CURRENT)):
h = canvas.create_oval(x-r, y-r, x+r, y+r)
canvas.tag_bind(h, '<Enter>', lambda e,hh=h: canvas.itemconfig(hh,fill='#FF0000'))
canvas.tag_bind(h, '<Leave>', lambda e,hh=h: canvas.itemconfig(hh,fill=''))
canvas.tag_bind(h, '<B1-Motion>', lambda e,hh=h: canvas.coords(hh,e.x-r,e.y-r,e.x+r,e.y+r))
if __name__ == '__main__':
canv = tk.Canvas(width=400, height=300, bg='#CCCCFF')
canv.bind('<Button-1>',lambda e: grabbablePoint(canv,e.x,e.y,3))
canv.pack()
tk.mainloop()
As a result, if I click on a point before moving off and back over, it spawns another point right on top of the first. Strangely, I can remedy this undesirable behavior by adding a fill attribute to create_oval ...
h = canvas.create_oval(x-r, y-r, x+r, y+r, fill='#FF0000')
Now it works perfectly. Can anybody explain to me what is happening here? Why does adding an attribute trigger CURRENT and why is it not set otherwise?
Upvotes: 2
Views: 134
Reputation: 4623
If you draw your shape without fill, from a Tkinter point of view, you are not hovering your shape, you are hovering the background. Without fill, only the stroke of the shape is sensible to mouse event (enter, leave, CURRENT...).
You can get around this using another method from find_
family: find_closest
, find_overlapping
.
Note that due to mouse event sampling, you can also get into an existing shape without triggering enter (jumping above the stroke), thus not displaying your background that imply your circle will not move, and you will create another circle (however unlikely with your radius and a mouse).
Upvotes: 1