Tkinter Canvas move(): Move Shapes, Images and Drag Items

The Tkinter Canvas move() method shifts an existing Canvas item by a horizontal and vertical distance. It can move rectangles, ovals, lines, text, images and groups of items identified by a Canvas tag.

canvas.move(item, dx, dy)

Move a Rectangle on Tkinter Canvas using move()

Canvas move() Syntax 🔝

canvas.move(tag_or_id, dx, dy)
ArgumentMeaning
tag_or_idCanvas item id or Canvas tag identifying the item or items to move.
dxHorizontal distance to move.
dyVertical distance to move.

Canvas coordinates normally increase from the top-left corner.

Movementdxdy
RightPositive0
LeftNegative0
Down0Positive
Up0Negative
Right and downPositivePositive
Important: The first argument is not a Tkinter widget. It is the Canvas item id returned by methods such as create_rectangle(), or a Canvas tag assigned to one or more items.

Move a Rectangle on Canvas 🔝

Move rectangle using Tkinter Canvas move method

create_rectangle() returns an item id. Pass this id to move().

import tkinter as tk

root=tk.Tk()
root.geometry('420x250')

canvas=tk.Canvas(root, width=400, height=170, bg='lightgreen')
canvas.pack(padx=10, pady=10)

rect=canvas.create_rectangle(20, 70, 50, 100, fill='red')

def move_rectangle():
    canvas.move(rect, 5, 5)

tk.Button(root, text='Move', command=move_rectangle).pack()

root.mainloop()

Each button click adds 5 pixels to both coordinates, so the rectangle moves right and down.

canvas.move(rect, 5, 5)

Move an Item in Four Directions 🔝

Move a Tkinter Canvas Rectangle with Buttons and Arrow Keys

One reusable function can move the item in any direction.

import tkinter as tk

root=tk.Tk()
root.geometry('420x300')

canvas=tk.Canvas(root, width=400, height=180, bg='lightgreen')
canvas.grid(row=0, column=0, columnspan=3, padx=10, pady=10)

rect=canvas.create_rectangle(190, 80, 220, 110, fill='red')
step=10

def move_item(dx, dy):
    canvas.move(rect, dx, dy)

tk.Button(root, text='Up', command=lambda: move_item(0, -step)).grid(row=1, column=1, sticky='ew')
tk.Button(root, text='Left', command=lambda: move_item(-step, 0)).grid(row=2, column=0, sticky='ew')
tk.Button(root, text='Down', command=lambda: move_item(0, step)).grid(row=2, column=1, sticky='ew')
tk.Button(root, text='Right', command=lambda: move_item(step, 0)).grid(row=2, column=2, sticky='ew')

root.mainloop()

Move a Canvas Item with Arrow Keys 🔝

Keyboard events can call the same movement function.

root.bind('<Right>', lambda event: move_item(step, 0))
root.bind('<Left>', lambda event: move_item(-step, 0))
root.bind('<Up>', lambda event: move_item(0, -step))
root.bind('<Down>', lambda event: move_item(0, step))

The event callback receives an event object, so the lambda accepts event before calling the regular movement function.

Tkinter Events

Canvas move() vs coords() 🔝

move() changes an item's position relative to where it is now.

canvas.move(rect, 10, 0)

This means:

Move the rectangle 10 pixels to the right.

coords() can read or replace an item's coordinates.

canvas.coords(rect, 50, 60, 100, 110)

This means:

Place the rectangle at these coordinates.
MethodUse
move(item, dx, dy)Relative movement from the current position
coords(item)Read the item's current coordinates
coords(item, ...)Replace the item's coordinates

Read the Current Item Position 🔝

For a rectangle:

print(canvas.coords(rect))
Sample Output
[20.0, 70.0, 50.0, 100.0]

These values represent:

[x1, y1, x2, y2]

For an image using its default center anchor:

print(canvas.coords(image_item))
Sample Output
[100.0, 80.0]

Keep a Moving Item inside the Canvas 🔝

Without a boundary check, repeated movement can move an item completely outside the visible Canvas.

bbox() returns the bounding rectangle of a Canvas item.

print(canvas.bbox(rect))

We can use it before moving:

def move_inside(dx, dy):
    x1, y1, x2, y2=canvas.bbox(rect)
    width=int(canvas.cget('width'))
    height=int(canvas.cget('height'))

    if x1+dx < 0 or x2+dx > width:
        dx=0

    if y1+dy < 0 or y2+dy > height:
        dy=0

    canvas.move(rect, dx, dy)

Now movement stops at the Canvas boundary.

Move Multiple Canvas Items with a Tag 🔝

A Canvas tag can identify several items. Passing that tag to move() moves every matching item.

canvas.create_rectangle(30, 30, 80, 70, fill='lightblue', tags='group1')
canvas.create_text(55, 50, text='Move', tags='group1')

canvas.move('group1', 20, 10)

Both the rectangle and text move together.

Move an Image on Canvas 🔝

Move image on Tkinter Canvas

create_image() also returns a Canvas item id, so it can be passed directly to move().

import tkinter as tk

root=tk.Tk()

canvas=tk.Canvas(root, width=500, height=300, bg='lightgreen')
canvas.pack()

photo=tk.PhotoImage(file='plus2net.png')
image_item=canvas.create_image(100, 80, image=photo)

canvas.move(image_item, 20, 10)

root.mainloop()

By default, the coordinates passed to create_image() represent the center of the image.

If top-left coordinates are easier for the application:

image_item=canvas.create_image(100, 80, image=photo, anchor='nw')
Tkinter Images

Drag an Image with the Mouse 🔝

Drag image using mouse on Tkinter Canvas

The cleanest approach is to bind mouse events directly to the Canvas image item. This means dragging starts only when the user presses the mouse button over that image.

import tkinter as tk

root=tk.Tk()
root.geometry('620x420')

canvas=tk.Canvas(root, width=600, height=360, bg='lightgreen')
canvas.pack(padx=10, pady=10)

photo=tk.PhotoImage(file='plus2net.png')
image_item=canvas.create_image(120, 100, image=photo)

drag_data={'x': 0, 'y': 0}

def start_drag(event):
    drag_data['x']=event.x
    drag_data['y']=event.y

def drag(event):
    dx=event.x-drag_data['x']
    dy=event.y-drag_data['y']

    canvas.move(image_item, dx, dy)

    drag_data['x']=event.x
    drag_data['y']=event.y

canvas.tag_bind(image_item, '<ButtonPress-1>', start_drag)
canvas.tag_bind(image_item, '<B1-Motion>', drag)

root.mainloop()

When the mouse button is first pressed, the code stores the mouse coordinates:

drag_data['x']=event.x
drag_data['y']=event.y

During movement, the change is calculated:

dx=event.x-drag_data['x']
dy=event.y-drag_data['y']

The image moves by exactly the same change:

canvas.move(image_item, dx, dy)

This avoids the jump that can occur when the image is immediately moved to the mouse pointer's absolute coordinates.

Drag Multiple Canvas Items Independently 🔝

When several Canvas items are draggable, the built-in current tag identifies the item currently under the mouse pointer.

import tkinter as tk

root=tk.Tk()

canvas=tk.Canvas(root, width=500, height=300, bg='white')
canvas.pack()

canvas.create_rectangle(50, 50, 120, 100, fill='red', tags='draggable')
canvas.create_oval(180, 60, 240, 120, fill='lightblue', tags='draggable')

drag_data={'item': None, 'x': 0, 'y': 0}

def start_drag(event):
    current=canvas.find_withtag('current')

    if current:
        drag_data['item']=current[0]
        drag_data['x']=event.x
        drag_data['y']=event.y

def drag(event):
    item=drag_data['item']

    if item is None:
        return

    dx=event.x-drag_data['x']
    dy=event.y-drag_data['y']

    canvas.move(item, dx, dy)

    drag_data['x']=event.x
    drag_data['y']=event.y

def stop_drag(event):
    drag_data['item']=None

canvas.tag_bind('draggable', '<ButtonPress-1>', start_drag)
canvas.tag_bind('draggable', '<B1-Motion>', drag)
canvas.tag_bind('draggable', '<ButtonRelease-1>', stop_drag)

root.mainloop()

Both shapes share the draggable tag, but only the item under the pointer is stored and moved.

Drag and Drop without Canvas

Common Canvas move() Mistakes 🔝

1. Calling the First Argument a Widget

This:

rect=canvas.create_rectangle(10, 10, 50, 50)
canvas.move(rect, 10, 0)

uses a Canvas item id. rect is not a Tkinter widget.

2. Confusing Relative and Absolute Movement

This moves relative to the current location:

canvas.move(rect, 20, 10)

This changes the coordinates directly:

canvas.coords(rect, 50, 60, 100, 110)

3. Forgetting that Positive y Moves Down

Move up:

canvas.move(rect, 0, -10)

Move down:

canvas.move(rect, 0, 10)

4. Passing a Dummy Event to a Button Function

Instead of:

command=lambda: my_move('x')

use:

command=my_move

when the function does not need an event object.

5. Binding Dragging to the Whole Window

If one Canvas item should be draggable, bind the event directly to that item:

canvas.tag_bind(image_item, '<ButtonPress-1>', start_drag)
canvas.tag_bind(image_item, '<B1-Motion>', drag)

6. Not Saving the Initial Mouse Position

A drag calculation requires the previous mouse coordinates:

drag_data['x']=event.x
drag_data['y']=event.y

Without this, the first movement can jump by an incorrect offset.

7. Moving Every Image Together Accidentally

Use an individual item id or determine the item under the pointer instead of always moving a single global collection.

8. Losing the PhotoImage Reference

Keep the image object in a variable:

photo=tk.PhotoImage(file='plus2net.png')
image_item=canvas.create_image(100, 80, image=photo)

9. Hard-Coding an Image Path from Another Computer

Prefer a project-relative file such as:

photo=tk.PhotoImage(file='plus2net.png')

or build the path from the application's directory.

10. Allowing the Item to Move outside the Canvas

Use bbox() to check its current visual bounds when movement must remain inside the visible Canvas.

Summary of Tkinter Canvas move() 🔝

  • Canvas.move() moves an existing Canvas item by a relative offset.
  • The syntax is move(tag_or_id, dx, dy).
  • The first argument is a Canvas item id or tag, not a Tkinter widget.
  • Canvas creation methods such as create_rectangle() return item ids.
  • Positive x moves right and negative x moves left.
  • Positive y moves down and negative y moves up.
  • Use move() for relative movement.
  • Use coords() when reading or replacing coordinates.
  • Use bbox() when the item's displayed bounding box is required.
  • Buttons can call one reusable function with different dx and dy values.
  • Arrow-key bindings can call the same movement function.
  • Passing a Canvas tag to move() moves all matching items.
  • Images created by create_image() can be moved like other Canvas items.
  • Keep a reference to the PhotoImage while it is displayed.
  • Use tag_bind() to attach dragging directly to a Canvas item.
  • Store the previous mouse position and move by the difference during dragging.
  • The built-in current tag can identify the item under the mouse pointer.
  • Multiple Canvas objects can share a custom tag such as draggable.
  • Use bbox() checks when objects must remain inside Canvas boundaries.
Tkinter Canvas Canvas Animation Sin & Cos Curves Drag and Drop




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
©2000-2026   plus2net.com   All rights reserved worldwide Privacy Policy Disclaimer