2016-08-03 20 views
2

verwenden ich den Code unter dem ich im Internet fand eine Maus Schweben Aktion in Python zu implementieren:Wie implementiert man einen Mouseover-Callback auf Canvas-Elemente in tkinter?

from tkinter import * 
import numpy as np 

class 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() 

    def motion(self,event): 
     if self.canvas.find_withtag(CURRENT): 
      current_color = self.canvas.itemcget(CURRENT, 'fill') 
      self.canvas.itemconfig(CURRENT, fill="cyan") 
      self.canvas.update_idletasks() 
      self.canvas.after(150) 
      self.canvas.itemconfig(CURRENT, fill=current_color) 

    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() 

Das Problem bei der Ausführung ist, dass die Farbe der Option wechselt zu Blau nur für eine begrenzte Zeit.

Ich brauche die Farbe jedes Elements in der Leinwand, die geändert werden soll, wenn ich die Zone betrete und blau bleibe, bis die Maus das Objekt verlässt.

+0

'event.widget.find_closest (event.x, event.y)' gab einen Index zurück Nummer, aber wenn Sie zufällig erstellen, haben Sie eine Menge Schmerzen. – dsgdfg

Antwort

0

änderte ich motion Methode und hinzugefügt self.last = None-__init__ Methode:

from tkinter import * 
import numpy as np 

class 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() 
3

Sie activefill das Argument übergeben können, wenn Ihr Rechteck zu schaffen.

Von effboot.org:

Fill Farbe zu verwenden, wenn der Mauszeiger über das Element bewegt wird, wenn anders füllen.

so zu tun, ersetzen:

rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red') 

Von:

rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red', activefill='cyan') 

Dadurch wird die Notwendigkeit beseitigt Motion auf der Leinwand zu binden, und macht auch den Code noticebly kürzer:

from tkinter import * 
import numpy as np 

class 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() 
+0

Danke Mann. das war wirklich cool. Es hat meinen Code sehr optimiert. –