When I catch motion in rectangle widget in a canvas it work propertly but when i draw mouseposition in canvas the whidet box event is not trigged anymore
To see the proble just uncomment lines in canvmove function.
Thanks for your help.
from tkinter import *
class box():
def __init__(self, canvas, startx, starty, endx, endy, **opts):
self.canvas = canvas
self.startx, self.starty, self.endx, self.endy=startx, starty, endx, endy
self.index=self.canvas.create_rectangle(self.startx, self.starty, self.endx, self.endy, fill='orange')
self.tag="BoundingBox" str(self.index)
self.canvas.addtag(self.tag, 'withtag',self.index)
self.canvas.tag_bind(self.tag, '<Leave>', lambda event,t=self.tag:self.boxleave(event,self.tag))
self.canvas.tag_bind(self.tag, '<Motion>', lambda event:self.boxmotion(event,self.tag))
def boxleave(self, event, tag):
self.canvas.itemconfig(tag, fill="orange")
def boxmotion(self, event, tag):
# print("box motion ", event.x, event.y)
self.canvas.itemconfig(tag, fill="red")
def showcursorpos(self, event,t):
self.canvas.delete('mousepos')
def canvmove(event):
# print("canvas motion ", event.x, event.y)
dashes = [5, 25]
canvas.delete('mousepos')
# **********************************************************************
# WHEN ACTIVATING LINES BELOW THE BOXMOTION EVENT DOESN'T TRIGGER
# canvas.create_line(event.x, 0, event.x, 1000, dash=dashes, tags='mousepos')
# canvas.create_line(0, event.y, 1000, event.y, dash=dashes, tags='mousepos')
# **********************************************************************
root = Tk()
canvas = Canvas(root, background="white")
canvas.bind("<Motion>", canvmove)
label = Label(root)
for x in range(0, 200, 50):
for y in range(0, 200, 50):
# create unique tag
tag = 'rectangle_%s_%s' % (x,y)
rect = box(canvas, x,y,x 40,y 40)
canvas.grid()
label.grid()
root.mainloop()
CodePudding user response:
Here is a slightly different way to achieve the same or similar results.
The tag
consists of fill, outline and activefill colors and is applied to each rectangle as they are created.
The act
method handles dashed cross hairs by offsetting the lines by a 3 points.
This allows both cross hair and rectangle interactions.
import tkinter as tk
class box:
def __init__(self):
self.master = tk.Tk()
self.canvas = tk.Canvas(self.master)
self.canvas.grid(sticky = tk.NSEW)
self.rect = []
tag = dict(fill = "orange", outline = "black", activefill = "red")
for x in range(2, 202, 50):
for y in range(2, 202, 50):
self.rect.append(
self.canvas.create_rectangle(x,y,x 40,y 40, tag))
dashes = [5, 25]
self.itemLine1 = self.canvas.create_line(0, 0, 0, 1000,
dash = dashes, fill = "black")
self.itemLine2 = self.canvas.create_line(0, 0, 1000, 0,
dash = dashes, fill = "black")
self.canvas.bind( "<Motion>", self.act)
def act(self, ev):
self.canvas.coords( self.itemLine1, ev.x 3, 0, ev.x 3, 1000)
self.canvas.coords( self.itemLine2, 0, ev.y 3, 1000, ev.y 3)
app = box()
app.master.mainloop()
This is perhaps a better replacement of method act
.
The cursor is turned on when over a rectangle and cross hairs turned off. When cursor is not over rectangle then cross hair is on and cursor is off.
def act(self, ev):
i = self.canvas.find_enclosed(ev.x-40, ev.y-40, ev.x 40, ev.y 40)
if i and i[0] in self.rect:
self.canvas.itemconfig(self.itemLine1, state = "hidden")
self.canvas.itemconfig(self.itemLine2, state = "hidden")
self.canvas["cursor"] = "crosshair"
else:
self.canvas["cursor"] = "none"
self.canvas.itemconfig(self.itemLine1, state = "normal")
self.canvas.itemconfig(self.itemLine2, state = "normal")
self.canvas.coords( self.itemLine1, ev.x, 0, ev.x, 1000)
self.canvas.coords( self.itemLine2, 0, ev.y, 1000, ev.y)
CodePudding user response:
I've been tinking all day and I found a way to achieve what I needed : In fact when drawind lines, I asume the cursor is not on a rectangle but on de line newly created... So, I tried changing the way of drawing the lines and draw them arround the mouse position ( 3 x-y) and the event trigger as well !!
Thanks for your answer Derek !!!
canvas.create_line(event.x, 0, event.x, event.y-3, dash=dashes, tags='mousepos')
canvas.create_line(event.x, event.y 3, event.x, 1000, dash=dashes, tags='mousepos')
canvas.create_line(0, event.y, event.x-3, event.y, dash=dashes, tags='mousepos')
canvas.create_line(event.x 3, event.y, 1000, event.y, dash=dashes, tags='mousepos')
Solved then ;)