How to enable drag and drop of objects in tkinter canvas?

I have this piece of code:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
frame = tk.Frame(root)
frame.pack()

Bottom = tk.Frame(root)
Bottom.pack(side = tk.BOTTOM)
CanvasArea = ttk.Frame(Bottom)
CanvasArea.pack(side = tk.LEFT)
LeftGrid = tk.Frame(CanvasArea)
LeftGrid.pack(side = tk.LEFT)

def MakeDraggable(widget):
    widget.bind("<Button-1>", OnDragStart)
    widget.bind("<B1-Motion>", OnDragMotion)

def OnDragStart(event):
    widget = event.widget
    widget._drag_start_x = exent.x
    widget._drag_start_y = exent.y

def OnDragMotion(event):
    widget = event.widget
    x = widget.winfo_x() - widget._drag_start_x + event.x
    y = widget.winfo_y() - widget._drag_start_y + event.y
    widget.place(x = x, y = y)

class DragDropMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        make_draggable(self)

CW = 600
CH = 450
LXM = (CW / 2)
LYM = (CH / 2)
TLX = tk.IntVar()
TLY = tk.IntVar()

TLXInput = ttk.Entry(LeftGrid, textvariable = TLX)
TLXInput.grid(row = 2, column = 1)
TLYInput = ttk.Entry(LeftGrid, textvariable = TLY)
TLYInput.grid(row = 3, column = 1)

MainCanvas = tk.Canvas(CanvasArea, bg = 'white', height = CH, width = CW)
MainCanvas.pack(side = tk.LEFT)

N = 0

ObjectList = [0]

def MakeRect():
    Pum = N
    Rectangle = MainCanvas.create_rectangle((LXM + TLX.get()), (LYM + TLY.get()), (LXM + TLX.get()), (LYM + TLY.get()), fill = 'red', outline = 'black', width = 1, tags = Pum)
    MakeDraggable(Rectangle)
    ObjectList.insert(Pum, Rectangle)
    Pum = N + 1
    return Pum

AddRect = tk.Button(LeftGrid, text = 'Make Rectangle', command = MakeRect)
AddRect.grid(row = 4, column = 1)

I tried to put a drag and drop function solution into the canvas objects. It didn’t work. Error says:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\User\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:/Users/User/AppData/Local/Programs/Python/Python311/PASS/PA/Help.py", line 58, in MakeRect
    MakeDraggable(Rectangle)
  File "C:/Users/User/AppData/Local/Programs/Python/Python311/PASS/PA/Help.py", line 16, in MakeDraggable
    widget.bind("<Button-1>", OnDragStart)
    ^^^^^^^^^^^
AttributeError: 'int' object has no attribute 'bind'

Previously the def and objects part was this:

MainCanvas = tk.Canvas(CanvasArea, bg = 'white', height = CH, width = CW)
MainCanvas.pack(side = tk.LEFT)

N = 0

ObjectList = [0]

def MakeRect():
    Pum = N
    ObjectList.insert(Pum, MainCanvas.create_rectangle(((LXM + TLX.get()) + TSX.get()), ((LYM + TLY.get()) + TSY.get()), (LXM + TLX.get()), (LYM + TLY.get()) -, fill = 'red', outline = 'black', width = 1, tags = Pum))
    Pum = N + 1
    return Pum

Tell me, is it possible to put drag and drop on canvas objects?

Please post a short, runnable program that shows the problem, and include any traceback.

I have redone it, but instead of the “bad screen” error I was looking for, I got a “int object has no attribute” error. I can give you the file if you want.

Sorry for double.

Canvas items are not widgets. Canvas.create_xyq return an int id that you can use to configure.

Read tkinter.dnd doc and see if you can make it work. (I have never used it.)

Well, this is interesting. I asked Bing Chat and it gave me this, which works!

import tkinter as tk

def drag_start(event):
    widget = event.widget
    widget._drag_start_x = event.x
    widget._drag_start_y = event.y

def drag_motion(event):
    widget = event.widget
    x = widget.winfo_x() - widget._drag_start_x + event.x
    y = widget.winfo_y() - widget._drag_start_y + event.y
    widget.place(x=x, y=y)

root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()

rect = canvas.create_rectangle(10, 10, 50, 50, fill="blue")

canvas.tag_bind(rect, "<Button-1>", drag_start)
canvas.tag_bind(rect, "<B1-Motion>", drag_motion)

root.mainloop()