Hola,
como tkinter no trae de "fábrica" esta funcionalidad, pongo aqui un pequeño ejemplo (muy simple) de como hacerlo. El programa en si no hace otra cosa que mover un grafico sobre la pantalla (sin tener en cuenta los limites de los bordes).
Hay algun código que se puede cosiderar redundante como : .bind("<Button-1>") y .bind("<ButtonPress-1>"). Pero el ejemplo es solo a efectos didácticos. La librería PIL / Pillow se puede omitir, pero es que me siento cómodo con ella.
Espero os sirva.
Saludos
como tkinter no trae de "fábrica" esta funcionalidad, pongo aqui un pequeño ejemplo (muy simple) de como hacerlo. El programa en si no hace otra cosa que mover un grafico sobre la pantalla (sin tener en cuenta los limites de los bordes).
Hay algun código que se puede cosiderar redundante como : .bind("<Button-1>") y .bind("<ButtonPress-1>"). Pero el ejemplo es solo a efectos didácticos. La librería PIL / Pillow se puede omitir, pero es que me siento cómodo con ella.
Código:
from tkinter import *
from PIL import Image, ImageTk
class ArrastraSuelta:
def __init__(self, raiz, ancho_x, alto_y):
self.raiz = raiz
# estas medidas serán las mismas que el programa emisor
# se utilizarán como coordenadas para los clicks, frames, etc.
self.ancho_x = ancho_x
self.alto_y = alto_y
# Este diccionario lo usaremos para mantener el rastro de un un drag & drop
self._drag_data = {"x": 0, "y": 0, "item": None}
self.fm_prin = Frame(self.raiz, height=self.alto_y, width=self.ancho_x)
#self.fm_prin.pack(expand = True, fill = "none")
self.fm_prin.pack()
self.lienzo = Canvas(self.fm_prin, width=self.ancho_x, height=self.alto_y)
self.lienzo.pack(expand = YES, fill = BOTH)
ancho_lienzo = self.lienzo.winfo_width()
alto_lienzo = self.lienzo.winfo_height()
#imagen de fondo inicial
img = Image.open('./iconos/fondo_visor.jpg')
tkimg = ImageTk.PhotoImage(img)
self.img_frames = self.lienzo.create_image(ancho_lienzo/2, \
alto_lienzo/2, anchor=NW, image = tkimg, tag="nombre1")
self.lienzo.image = tkimg # para mantener la referencia
# ahora vinculo los botones y teclas al canvas
# boton izquierdo y derecho
self.lienzo.bind("<Button-3>", self.onclick_derecho)
self.lienzo.bind("<Button-1>", self.onclick_izquierdo)
# pasos para el drag & drop con el boton izquierdo
self.lienzo.tag_bind("nombre1", "<ButtonPress-1>", self.inicia_drag)
self.lienzo.tag_bind("nombre1", "<Button-1>", self.moviendo_drag)
self.lienzo.tag_bind("nombre1", "<ButtonRelease-1>", self.suelta_drag)
# la captura de la tecla no se puede hacer sobre un Canvas
self.raiz.bind("<Key>", self.onTecla_presionada)
def onclick_derecho(self, evento):
#obtenemos las coords. x, y
x = evento.x
y = evento.y
print(46, x, y)
def onclick_izquierdo(self, evento):
#obtenemos las coords. x, y
x = evento.x
y = evento.y
print(53, x, y)
def onTecla_presionada(self, evento):
#capturamos la tecla
teclaPresionada = evento.char
print(64, str(teclaPresionada))
def inicia_drag(self, evento):
#registramos el tema y su localizacion
self.origen = None
self._drag_data["item"] = self.lienzo.find_closest(evento.x, evento.y)[0]
self._drag_data["x"] = evento.x
self._drag_data["y"] = evento.y
self.origen = (evento.x, evento.y)
print(74, evento.x, evento.y)
def moviendo_drag(self, evento):
'''Maneja el arrastre del raton'''
if self.origen == None:
# reseteamos la informacion de _drag_data
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
else:
# calcula cuanto se ha movido el raton
distancia_x = evento.x - self._drag_data["x"]
distancia_y = evento.y - self._drag_data["y"]
# muevo el objeto la distancia apropiada
self.lienzo.move(self._drag_data["item"], distancia_x, distancia_y)
# retomo la nueva posicion
self._drag_data["x"] = evento.x
self._drag_data["y"] = evento.y
print(93, evento.x, evento.y)
def suelta_drag(self, evento):
'''Final del arrastre de la pieza'''
# reseteamos la informacion del arrastre
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
x = evento.x
y = evento.y
print(105, x, y)
def inicia_prueba():
NOMBRE_PROGRAMA = 'Visor Recibe Escritorio'
ancho_x = 600
alto_y = 600
root = Tk()
root.geometry(str(ancho_x) + 'x' + str(alto_y) +'+500+1') # la diferencia es el alo del menu
root.title(NOMBRE_PROGRAMA)
#img = PhotoImage(file='./iconos/pantalla.png')
#root.tk.call('wm', 'iconphoto', root._w, img)
cierra_win = ArrastraSuelta(root, ancho_x, alto_y)
root.mainloop()
if __name__ == '__main__':
inicia_prueba()
Espero os sirva.
Saludos