Otro algoritmo útil cuando trabajamos con figuras dentro de un control Canvas es la posibilidad de arrastrar y soltar figuras.
Debemos capturar los eventos cuando se hace clic dentro de una figura y luego cada vez que se desplaza la flecha del mouse.
Se cuenta con dos archivos de tipo png con las imágenes de distintas cartas. Mostrarlas a cada una dentro de una componente de tipo Canvas y permitir moverlas dentro del control mediante el mouse.
Puede descargar estas dos imágenes y copiarlas en la carpeta donde codifica sus programas en Python:
La interfaz visual debe ser similar a esta luego de mover con el mouse las imágenes:
import tkinter as tk class Aplicacion: def __init__(self): self.ventana1=tk.Tk() self.canvas1=tk.Canvas(self.ventana1, width=900, height=500, background="black") self.canvas1.grid(column=0, row=0) archi1=tk.PhotoImage(file="carta1.png") self.canvas1.create_image(30, 100, image=archi1, anchor="nw", tags="movil") archi2=tk.PhotoImage(file="carta2.png") self.canvas1.create_image(400, 100, image=archi2, anchor="nw", tags="movil") self.canvas1.tag_bind("movil", "<ButtonPress-1>", self.presion_boton) self.canvas1.tag_bind("movil", "<Button1-Motion>", self.mover) self.carta_seleccionada = None self.ventana1.mainloop() def presion_boton(self, evento): carta = self.canvas1.find_withtag(tk.CURRENT) self.carta_seleccionada = (carta, evento.x, evento.y) def mover(self, evento): x, y = evento.x, evento.y carta, x1, y1 = self.carta_seleccionada self.canvas1.move(carta, x - x1, y - y1) self.carta_seleccionada = (carta, x, y) aplicacion1=Aplicacion()
Creamos primero el control de tipo Canvas y las dos imágenes respectivas. A cada una de las imágenes iniciamos el parámetro 'tags' con un valor:
self.canvas1=tk.Canvas(self.ventana1, width=900, height=500, background="black") self.canvas1.grid(column=0, row=0) archi1=tk.PhotoImage(file="carta1.png") self.canvas1.create_image(30, 100, image=archi1, anchor="nw", tags="movil") archi2=tk.PhotoImage(file="carta2.png") self.canvas1.create_image(400, 100, image=archi2, anchor="nw", tags="movil")
Mediante el método 'tag_bind' de la clase Canvas enlazamos el evento de presión del botón izquierdo para todas las figuras que tienen el tag con el valor 'movil':
self.canvas1.tag_bind("movil", "<ButtonPress-1>", self.presion_boton)
De forma idéntica hacemos la captura del desplazamiento del mouse:
self.canvas1.tag_bind("movil", "<Button1-Motion>", self.mover)
Inicializamos el atributo 'carta_seleccionada' con el valor None, indicando que ninguna de las cartas se ha hecho clic sobre la misma:
self.carta_seleccionada = None
Cuando se presiona el botón izquierdo sobre alguna de las cartas se extrae mediante el método 'find_withtag' la referencia de la carta presionada y se guarda en el atributo 'carta_seleccionada' una tupla que contiene la carta que se acaba de presionar y la coordenada x e y actual:
def presion_boton(self, evento): carta = self.canvas1.find_withtag(tk.CURRENT) self.carta_seleccionada = (carta, evento.x, evento.y)
Cuando se mueve la flecha del mouse extraemos del atributo 'carta_seleccionada' la carta que se había presionado y su coordenada, procedemos a desplazarla mediante el método 'move' y guardamos la nueva posición de la carta:
def mover(self, evento): x, y = evento.x, evento.y carta, x1, y1 = self.carta_seleccionada self.canvas1.move(carta, x - x1, y - y1) self.carta_seleccionada = (carta, x, y)
Crear 100 cuadrados de color rojo y disponerlos en el control Canvas en posiciones aleatorias. Permitir desplazar con el mouse cualquiera de los cuadrados.
ejercicio266.py import tkinter as tk import random class Aplicacion: def __init__(self): self.ventana1=tk.Tk() self.canvas1=tk.Canvas(self.ventana1, width=900, height=500, background="black") self.canvas1.grid(column=0, row=0) for x in range(101): x1=random.randint(1,900) y1=random.randint(1,500) self.cuadrado=self.canvas1.create_rectangle(x1, y1, x1+20, y1+20, fill="red", outline="red", tags="movil") self.canvas1.tag_bind("movil", "<ButtonPress-1>", self.presion_boton) self.canvas1.tag_bind("movil", "<Button1-Motion>", self.mover) self.carta_seleccionada = None self.ventana1.mainloop() def presion_boton(self, evento): carta = self.canvas1.find_withtag(tk.CURRENT) self.carta_seleccionada = (carta, evento.x, evento.y) def mover(self, evento): x, y = evento.x, evento.y carta, x1, y1 = self.carta_seleccionada self.canvas1.move(carta, x - x1, y - y1) self.carta_seleccionada = (carta, x, y) aplicacion1=Aplicacion()