How to implement a mouse hovering callback on canvas items in tkinter?
You can pass the argument activefill
when creating your rectangle.
From effboot.org:
Fill color to use when the mouse pointer is moved over the item, if different from fill.
To do so, replace:
rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red')
By:
rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red', activefill='cyan')
This removes the need to bind Motion
to your canvas, and also makes the code noticebly shorter:
from tkinter import *import numpy as npclass rect: def __init__(self, root): self.root = root self.size = IntVar() self.canvas = Canvas(self.root, width=800, height=300) self.scale = Scale(self.root, orient=HORIZONTAL, from_=3, to=20, tickinterval=1, variable=self.size) self.scale.bind('<ButtonRelease>', self.show) self.board = [] self.array = np.zeros((self.scale.get(),self.scale.get())).tolist() self.canvas.pack() self.scale.pack() def show(self,event): self.canvas.delete('all') x = 50 y = 50 row = [] self.board.clear() for i in range(self.scale.get()): row = [] for j in range(self.scale.get()): rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red', activefill='cyan') x += 50 row.append(rectangle) x -= j*50 y +=50 self.board.append(row) print(self.board)root = Tk()a = rect(root)root.mainloop()
I changed motion
method and added self.last = None
to __init__
method:
from tkinter import *import numpy as npclass rect: def __init__(self, root): self.root = root self.size = IntVar() self.canvas = Canvas(self.root, width=800, height=300) self.scale = Scale(self.root, orient=HORIZONTAL, from_=3, to=20, tickinterval=1, variable=self.size) self.scale.bind('<ButtonRelease>', self.show) self.canvas.bind('<Motion>', self.motion) self.board = [] self.array = np.zeros((self.scale.get(),self.scale.get())).tolist() self.canvas.pack() self.scale.pack() self.last = None def motion(self, event): temp = self.canvas.find_withtag(CURRENT) if temp == self.last: self.canvas.itemconfig(CURRENT, fill="cyan") self.canvas.update_idletasks() else: self.canvas.itemconfig(self.last, fill="red") self.last = temp def show(self,event): self.canvas.delete('all') x = 50 y = 50 row = [] self.board.clear() for i in range(self.scale.get()): row = [] for j in range(self.scale.get()): rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red') x += 50 row.append(rectangle) x -= j*50 y +=50 self.board.append(row) print(self.board)root = Tk()a = rect(root)root.mainloop()