pythontkintercanvasscreenmove

move an image between two canvases in python


I would like to ask how can I move one image from upper canvas to lower canvas in python? here is my code which I would like to move an image from upper canvas to lower canvas:

from tkinter import *
from tkinter import font
from PIL import Image, ImageTk
import os

os.system("cls||clear")

def on_drag1(event):
    cw1.moveto(image11,x = cw1.winfo_pointerx() - cw1.winfo_rootx(),
                      y = cw1.winfo_pointery() - cw1.winfo_rooty())

def on_drop1(event):
    cw2.moveto(image11,x = cw2.winfo_pointerx() - cw2.winfo_rootx(),
                      y = cw2.winfo_pointery() - cw2.winfo_rooty()) 

win = Tk()

style = font.Font(size=20)

cw1 = Canvas(win,width=350, height=350,bg = "khaki2")
cw1.pack(fill="both",expand=True)

cw2 = Canvas(win, width=350, height=350,bg="salmon")
cw2.pack(fill="both", expand=True)

image1 = ImageTk.PhotoImage(Image.open("E:\images\image1.jpg").
                        resize((100, 100), Image.Resampling.BICUBIC))

image11 = cw1.create_image(150, 150, image=image1,tags='image1Tag')

cw1.bind("<B1-Motion>",on_drag1)
cw1.bind("<ButtonRelease-1>",on_drop1)

win.geometry("650x650")
win.title("Draggable Widgets")
win.mainloop()

The problem is when I drag the image and wants to take it to lower canvas it goes behind the lower convas and will not show this image on the lower convas. Please let me know what is the problem and the remedy must take place. Thanks in advance


Solution

  • Without making draggable in the lower canvas:

    from tkinter import *
    from PIL import Image, ImageTk
    
    def on_drag(event):
        x, y = event.x, event.y
        cw1.coords(image_id, x, y)
    
    def on_drop(event):
        global image_id
    
        x, y = event.x, event.y
    
        abs_x = cw1.winfo_rootx() + x
        abs_y = cw1.winfo_rooty() + y
    
        cw2_x = cw2.winfo_rootx()
        cw2_y = cw2.winfo_rooty()
        cw2_width = cw2.winfo_width()
        cw2_height = cw2.winfo_height()
    
        if cw2_x <= abs_x <= cw2_x + cw2_width and cw2_y <= abs_y <= cw2_y + cw2_height:
            cw1.delete(image_id)
    
            new_x = abs_x - cw2_x
            new_y = abs_y - cw2_y
            image_id = cw2.create_image(new_x, new_y, image=image1, tags='image1Tag')
    
    win = Tk()
    win.geometry("650x650")
    win.title("Draggable Image Between Canvases")
    
    cw1 = Canvas(win, width=350, height=350, bg="khaki2")
    cw1.pack(fill="both", expand=True)
    
    cw2 = Canvas(win, width=350, height=350, bg="salmon")
    cw2.pack(fill="both", expand=True)
    
    image1 = ImageTk.PhotoImage(Image.open("plot.png").resize((100, 100), Image.Resampling.BICUBIC))
    
    image_id = cw1.create_image(150, 150, image=image1, tags='image1Tag')
    
    cw1.tag_bind(image_id, "<B1-Motion>", on_drag)
    cw1.tag_bind(image_id, "<ButtonRelease-1>", on_drop)
    
    win.mainloop()
    

    To make the image is draggable in the two canvases:

    from tkinter import *
    from PIL import Image, ImageTk
    
    def on_drag(event):
        x, y = event.x, event.y
        event.widget.coords(image_id, x, y)
    
    def on_drop(event):
        global image_id, current_canvas
    
        x, y = event.x, event.y
        abs_x = event.widget.winfo_rootx() + x
        abs_y = event.widget.winfo_rooty() + y
    
        target_canvas = None
    
        if cw1.winfo_rootx() <= abs_x <= cw1.winfo_rootx() + cw1.winfo_width() and \
           cw1.winfo_rooty() <= abs_y <= cw1.winfo_rooty() + cw1.winfo_height():
            target_canvas = cw1
        elif cw2.winfo_rootx() <= abs_x <= cw2.winfo_rootx() + cw2.winfo_width() and \
             cw2.winfo_rooty() <= abs_y <= cw2.winfo_rooty() + cw2.winfo_height():
            target_canvas = cw2
    
        if target_canvas and target_canvas != current_canvas:
            current_canvas.delete(image_id)
            new_x = abs_x - target_canvas.winfo_rootx()
            new_y = abs_y - target_canvas.winfo_rooty()
            image_id = target_canvas.create_image(new_x, new_y, image=image1, tags='image1Tag')
            current_canvas = target_canvas
    
            target_canvas.tag_bind(image_id, "<B1-Motion>", on_drag)
            target_canvas.tag_bind(image_id, "<ButtonRelease-1>", on_drop)
    
    win = Tk()
    win.geometry("650x650")
    win.title("Draggable Image Between Canvases")
    
    cw1 = Canvas(win, width=350, height=350, bg="khaki2")
    cw1.pack(fill="both", expand=True)
    
    cw2 = Canvas(win, width=350, height=350, bg="salmon")
    cw2.pack(fill="both", expand=True)
    
    image1 = ImageTk.PhotoImage(Image.open("plot.png").resize((100, 100), Image.Resampling.BICUBIC))
    
    image_id = cw1.create_image(150, 150, image=image1, tags='image1Tag')
    current_canvas = cw1
    
    cw1.tag_bind(image_id, "<B1-Motion>", on_drag)
    cw1.tag_bind(image_id, "<ButtonRelease-1>", on_drop)
    
    win.mainloop()
    

    Please review the code. Thank you.