Una actividad muy común es poder detectar cuando hemos presionado el mouse dentro de un control Canvas (o de cualquier otro Widget que hayamos visto) y a partir de eso disparar un evento.
Veremos con una serie de ejemplos la posibilidades de tkinter nos provee.
Confeccionar un programa que cree un objeto de la clase Canvas y nos muestre en el título de la ventana la coordenada actual del mouse dentro del control Canvas y al presionar el botón izquierdo del mouse se dibuje un círculo en dicha posición.
La interfaz visual debe ser similar a esta:
import tkinter as tk class Aplicacion: def __init__(self): self.ventana1=tk.Tk() self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background="black") self.canvas1.bind("<Motion>", self.mover_mouse) self.canvas1.bind("<Button-1>", self.presion_mouse) self.canvas1.grid(column=0, row=1) self.ventana1.mainloop() def presion_mouse(self, evento): self.canvas1.create_oval(evento.x-5,evento.y-5,evento.x+5,evento.y+5, fill="red") def mover_mouse(self, evento): self.ventana1.title(str(evento.x)+"-"+str(evento.y)) aplicacion1=Aplicacion()
Luego de crear el objeto de la clase Canvas procedemos a llamar al método bind e indicar el nombre de evento a capturar y el método que lo capturará:
self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background="black") self.canvas1.bind("<Motion>", self.mover_mouse) self.canvas1.bind("<Button-1>", self.presion_mouse)
Para capturar el desplazamiento de la flecha del mouse debemos especificar 'Motion' y la presión del botón izquierdo del mouse debemos especificar ''Button-1'.
Cada vez que se produce un desplazamiento de la flecha del mouse dentro de la componente canvas1 se ejecuta el método 'mover_mouse':
def mover_mouse(self, evento): self.ventana1.title(str(evento.x)+"-"+str(evento.y))
Todos los métodos que capturan eventos reciben un parámetro con información del evento propiamente dicho. Los atributos x e y almacenan la coordenada actual de la flecha del mouse.
El método 'presion_mouse' se dispara cuando presionamos el botón izquierdo del mouse dentro del objeto canvas1. Dibujamos un círculo teniendo en cuenta donde se encuentra la flecha del mouse en este momento:
def presion_mouse(self, evento): self.canvas1.create_oval(evento.x-5,evento.y-5,evento.x+5,evento.y+5, fill="red")
La diversidad de eventos que podemos capturar es muy grande, veamos algunos ejemplos:
Si necesitamos capturar el evento clic del botón derecho del mouse y a su vez que se encuentre presionada la tecla Shift tenemos que codificar:
self.canvas1.bind("<Shift Button-1>", self.presion_mouse)
En lugar de Shift podemos verificar si se está presionando la tecla control:
self.canvas1.bind("<Control Button-1>", self.presion_mouse)
Inclusive detectar el evento si se presiona Shift, Control y el botón izquierdo del mouse:
self.canvas1.bind("<Control Shift Button-1>", self.presion_mouse)
La tecla Alt, Shift, Control y el botón izquierdo del mouse:
self.canvas1.bind("<Control Shift Alt Button-1>", self.presion_mouse)
Si necesitamos hacer algo cuando la flecha del mouse entra al control podemos plantear la captura del evento:
self.canvas1.bind("<Enter>", self.entrada)
Y si queremos detectar cuando la flecha del mouse sale de la componente:
self.canvas1.bind("<Leave>", self.salida)
Para detectar el doble clic de un botón del mouse:
self.canvas1.bind("<Double-Button-1>", self.presion_mouse)
Confeccionar un programa que cree un objeto de la clase Canvas y nos permita dibujar a mano alzada dentro del mismo.
La interfaz visual debe ser similar a esta luego de dibujar unos trazos:
import tkinter as tk class Aplicacion: def __init__(self): self.ventana1=tk.Tk() self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background="black") self.canvas1.grid(column=0,row=0) self.canvas1.bind("<ButtonPress-1>",self.boton_presion) self.canvas1.bind("<Motion>", self.mover_mouse) self.canvas1.bind("<ButtonRelease-1>",self.boton_soltar) self.presionado=False self.ventana1.mainloop() def boton_presion(self, evento): self.presionado=True self.origenx=evento.x self.origeny=evento.y def mover_mouse(self, evento): if self.presionado: self.canvas1.create_line(self.origenx,self.origeny,evento.x,evento.y, fill="red") self.origenx=evento.x self.origeny=evento.y def boton_soltar(self,evento): self.presionado=False aplicacion1=Aplicacion()
Para poder dibujar a mano alzada vamos a identificar los eventos cuando se presiona el botón izquierdo del mouse:
self.canvas1.bind("<ButtonPress-1>", self.boton_presion)
Cuando se mueve el mouse dentro del control Canvas:
self.canvas1.bind("<Motion>", self.mover_mouse)
Y cuando se suelta el botón izquierdo del mouse:
self.canvas1.bind("<ButtonRelease-1>", self.boton_soltar)
Cuando se presiona el botón izquierdo del mouse se cambia el estado de la bandera 'presionado' y se definen los atributos origenx y origeny con la coordenada actual de la flecha del mouse:
def boton_presion(self, evento): self.presionado=True self.origenx=evento.x self.origeny=evento.y
Cada vez que se produce un desplazamiento de la flecha del mouse si la bandera 'presionado' tiene un valor 'True' se pasa a dibujar una línea desde la coordenada donde se encontraba la flecha del mouse cuando se lo presionó y la nueva coordenada, también actualizamos la coordenada origenx y origeny con la nueva posición:
def mover_mouse(self, evento): if self.presionado: self.canvas1.create_line(self.origenx,self.origeny,evento.x,evento.y, fill="red") self.origenx=evento.x self.origeny=evento.y
El método boton_soltar se ejecuta cuando el operador deja de presionar el botón izquierdo del mouse, donde volvemos a disponer el atributo 'presionado' con el valor 'False', lo que hace que cuando se mueve la flecha del mouse no se dibuje la línea:
def boton_soltar(self,evento): self.presionado=False