Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
How to move a Tkinter canvas with Mouse?
Tkinter Canvas widget is one of the versatile widgets in the Tkinter library. It is used to create different shapes, images, and animating objects. We can move images in a particular direction on the Canvas widget using the move() method.
Define the image and the coordinates as a parameter in the move(Image, x, y) method to move the object in the Canvas. We declare images globally in order to move or change the position.
We can follow these steps to allow our image to move within the canvas:
First, define the Canvas widget and add images to it.
Define the move() function to allow the image to be dynamic within the Canvas.
Bind the mouse buttons with the function that allows images to be moved within the Canvas.
Method 1: Moving Canvas Objects with Mouse Click and Drag
This approach creates a new image at each mouse position during dragging ?
# Import the required libraries
from tkinter import *
from PIL import Image, ImageTk
# Create an instance of tkinter frame
win = Tk()
# Set the size of the tkinter window
win.geometry("700x350")
# Define a Canvas widget
canvas = Canvas(win, width=600, height=400, bg="white")
canvas.pack(pady=20)
# Add Images to Canvas widget
image = ImageTk.PhotoImage(Image.open('logo.png'))
img = canvas.create_image(250, 120, anchor=NW, image=image)
def left(e):
x = -20
y = 0
canvas.move(img, x, y)
def right(e):
x = 20
y = 0
canvas.move(img, x, y)
def up(e):
x = 0
y = -20
canvas.move(img, x, y)
def down(e):
x = 0
y = 20
canvas.move(img, x, y)
# Define a function to allow the image to move within the canvas
def move(e):
global image
image = ImageTk.PhotoImage(Image.open('logo.png'))
img = canvas.create_image(e.x, e.y, image=image)
# Bind the move function
canvas.bind("<B1-Motion>", move)
win.mainloop()
Method 2: Better Approach Using Canvas Item Movement
A more efficient approach that moves the same object instead of creating multiple images ?
import tkinter as tk
# Create main window
root = tk.Tk()
root.title("Move Canvas Object with Mouse")
root.geometry("600x400")
# Create canvas
canvas = tk.Canvas(root, width=500, height=300, bg="lightblue")
canvas.pack(pady=20)
# Create a rectangle that we can move
rect = canvas.create_rectangle(50, 50, 100, 100, fill="red", outline="black")
# Variables to store mouse position
start_x = 0
start_y = 0
def on_click(event):
global start_x, start_y
start_x = event.x
start_y = event.y
def on_drag(event):
global start_x, start_y
# Calculate how far the mouse moved
dx = event.x - start_x
dy = event.y - start_y
# Move the rectangle
canvas.move(rect, dx, dy)
# Update start position for next movement
start_x = event.x
start_y = event.y
# Bind mouse events
canvas.bind("<Button-1>", on_click)
canvas.bind("<B1-Motion>", on_drag)
root.mainloop()
A window opens with a red rectangle that can be dragged around the canvas with the mouse.
Method 3: Moving Multiple Objects
You can also move multiple objects by detecting which item is clicked ?
import tkinter as tk
root = tk.Tk()
root.title("Move Multiple Canvas Objects")
root.geometry("600x400")
canvas = tk.Canvas(root, width=500, height=300, bg="white")
canvas.pack(pady=20)
# Create multiple objects
circle = canvas.create_oval(50, 50, 100, 100, fill="blue")
square = canvas.create_rectangle(150, 50, 200, 100, fill="green")
triangle = canvas.create_polygon(250, 50, 275, 100, 225, 100, fill="yellow")
# Variables for drag operation
selected_item = None
start_x = 0
start_y = 0
def on_click(event):
global selected_item, start_x, start_y
# Find the item under the mouse cursor
selected_item = canvas.find_closest(event.x, event.y)[0]
start_x = event.x
start_y = event.y
def on_drag(event):
global selected_item, start_x, start_y
if selected_item:
dx = event.x - start_x
dy = event.y - start_y
canvas.move(selected_item, dx, dy)
start_x = event.x
start_y = event.y
def on_release(event):
global selected_item
selected_item = None
# Bind events
canvas.bind("<Button-1>", on_click)
canvas.bind("<B1-Motion>", on_drag)
canvas.bind("<ButtonRelease-1>", on_release)
root.mainloop()
A window with three shapes (circle, square, triangle) that can each be individually dragged.
Key Points
<Button-1> - Left mouse button click event
<B1-Motion> - Mouse movement while left button is held down
<ButtonRelease-1> - Left mouse button release event
canvas.move(item, dx, dy) - Moves item by dx and dy pixels
canvas.find_closest(x, y) - Finds the canvas item closest to coordinates
Comparison
| Method | Performance | Use Case |
|---|---|---|
| Creating new images | Poor | Not recommended |
| Moving existing item | Good | Single object movement |
| Multiple object selection | Good | Interactive applications |
Conclusion
Use canvas.move() to efficiently move existing canvas items rather than creating new ones. Bind mouse events like <Button-1> and <B1-Motion> to enable drag-and-drop functionality for interactive canvas applications.
