Movement of items in Canvas

How to move any item on canvas ?

There are two ways to move the object in a Canvas.

Part 1 : Create Delete and Create

The basic concept of moving any item in canvas is to create , delete and then create the same item in new area by changing the coordinates. ( This is discussed here )

Part 2 : Using move()

Moving widgets or Images on Canvas by using move()

Moving element in Canvas

Moving objects in Tkinter Canvas in different directions by using buttons or by timer

Moving a rectangle

For a rectangle we have two coordinates ( x1, y1 ) and (x2, y2) .

Moving towards right side

While moving in horizontal direction (right side ) the coordinates for new locations will increase in x direction only. So the new location will be based on this formula. Here step is the variable whose value is the amount of jump or change the item will make.
x1=x1+step 
x2=x2+step

Moving towards left side

x1=x1-step x2=x2-step
To move vertically we have to change the y coordinate value. To move in up direction we have to reduce the value.
y1=y1-stepy2=y2-step
To move in downward direction we have to increase the y coordinate values.
y1=y1+stepy2=y2+step 

Making auto movement by using timer

We can repeat the movement by using timer after() , this will call the function after time delay in milliseconds.

Here time delay is 100 milliseconds and after the delay the function my_draw() is called.
c1.after(100,my_draw)

How long the movement is allowed ?

We don’t want the coordinates to fall beyond the boundaries of the Canvas. So when the coordinates reaches the edge of the boundary and next movement ( based on the step value ) will take the element to outside the canvas, we have to stop there.
def my_draw():    
    global x1,y1,x2,y2,r1
    c1.delete(r1) # delete the rectangle     
    r1=c1.create_rectangle(x1, y1, x2,y2,fill='red')
    if (x2<(c_width-step)): # check for right edge          x1,x2=x1+step,x2+step # new coordinates of rectangle        c1.after(100,my_draw)  # recursive call after delay           else:        return   # stop recursive call and return to main 
Full code is here
import tkinter as tk
my_w = tk.Tk()
width,height=410,210 # set the variables 
c_width,c_height=width-10,height-45 # canvas width height
d=str(width)+"x"+str(height)
my_w.geometry(d) 
c1 = tk.Canvas(my_w, width=c_width, height=c_height,bg='lightgreen')
c1.grid(row=1,column=0,padx=5,pady=5)
step=5 # value of each incremental movment, change this 
x1,y1=5,int(c_height/2) # starting position 
x2,y2=x1+15,y1+15      # starting position 
r1=c1.create_rectangle(x1, y1, x2,y2,fill='red')  # draw rectangle 
def my_draw():        global x1,y1,x2,y2,r1    c1.delete(r1) # delete the rectangle         r1=c1.create_rectangle(x1, y1, x2,y2,fill='red')    if (x2<(c_width-step)): # check for right edge          x1,x2=x1+step,x2+step # new coordinates of rectangle        c1.after(100,my_draw)  # recursive call after delay           else:        return   # stop recursive call and return to main 
my_draw() # start moving, remove this if not required at beginning 
def restart():    global x1,y1,x2,y2    x1,y1=5,int(c_height/2) # starting position     x2,y2=x1+15,y1+15      # starting position     my_draw() # start from starting position b1=tk.Button(my_w,text='Restart',command=lambda:restart())b1.grid(row=2,column=0)my_w.mainloop()

Using four directional buttons

In above code we have changed ( increased x or horizontal ) coordinates to move the rectangle in right direction.

Similarly we can decrease the x coordinates to move in left direction.
Increase the y coordinates to move in down direction.
Decrease the y coordinates to move in UP direction.

We will use four function to move the item in four different directions. We will add four buttons and each button will trigger the function based on the required direction. Inside the function we will control the coordinates to give the direction of movement to the element.
Moving item using buttons in Canvas
import tkinter as tk
my_w = tk.Tk()
width,height=610,410 # set the variables 
c_width,c_height=width-10,height-65 # canvas width height
d=str(width)+"x"+str(height)
my_w.geometry(d) 
c1 = tk.Canvas(my_w, width=c_width, height=c_height,bg='lightgreen')
c1.grid(row=0,column=0,padx=5,pady=5,columnspan=3)
step=10 # Jump in each movement, change this value
x1,y1,x2,y2=5,200,20,215  # initial locations of rectangle 
r1=c1.create_rectangle(x1, y1, x2,y2,fill='red')   
def right(event):    
    global x1,y1,x2,y2,r1
    if (x2<(c_width-step)):  # check right edge 
        x1=x1+step # increase the horizontal coordinates
        x2=x2+step    
        c1.delete(r1) # delete the rectangle         r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')def left(event):        global x1,y1,x2,y2,r1    if(x1 > step): # check left edge         x1=x1-step # decrease the horizontal coordiantes        x2=x2-step        c1.delete(r1) # delete the rectangle             r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')        def up(event):        global x1,y1,x2,y2,r1    if(y1 > step): # check top edge         y1=y1-step # decrease the vertical coordinates        y2=y2-step            c1.delete(r1) # delete the rectangle             r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')   def down(event):        global x1,y1,x2,y2,r1    if(y2 < c_height-step): # check bottom edge         y1=y1+step # increase the vertical coordinates        y2=y2+step        c1.delete(r1) # delete the rectangle             r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')            b1=tk.Button(my_w,text='Left',command=lambda:left('x'))b1.grid(row=1,column=0,rowspan=2,sticky='E')b2=tk.Button(my_w,text='Up',command=lambda:up('x'))b2.grid(row=1,column=1)b3=tk.Button(my_w,text='Right',command=lambda:right('x'))b3.grid(row=1,column=2,rowspan=2,sticky='W')b4=tk.Button(my_w,text='Down',command=lambda:down('x'))b4.grid(row=2,column=1)
my_w.mainloop()

Using Arrow Keys

We can connect the movement of the item to four directional arrow keys of our keyboard. The button and the arrow key press both can work so we will modify the function to receive the event like this.
def down(event):    # function declaration
#change the button click event. 
b4=tk.Button(my_w,text='Down',command=lambda:down('x'))
All four functions we have to change like above and the click event of all four buttons need to be changed.

We have to bind the four arrow keys like this.
my_w.bind('<Right>',right) # binding to right arrow key
my_w.bind('<Left>',left)   # left arrow key pressed
my_w.bind('<Up>',up)       # up arrow key 
my_w.bind('<Down>',down)   # down arrow key 
The full code
import tkinter as tkmy_w = tk.Tk()width,height=610,410 # set the variables c_width,c_height=width-10,height-65 # canvas width heightd=str(width)+"x"+str(height)my_w.geometry(d) 
c1 = tk.Canvas(my_w, width=c_width, height=c_height,bg='lightgreen')c1.grid(row=0,column=0,padx=5,pady=5,columnspan=3)step=10 # Jump in each movement, change this value x1,y1,x2,y2=5,200,20,215  # initial locations of rectangle r1=c1.create_rectangle(x1, y1, x2,y2,fill='red')   
def right(event):        global x1,y1,x2,y2,r1    if (x2<(c_width-step)):  # check right edge         x1=x1+step # increase the horizontal coordinates        x2=x2+step            c1.delete(r1) # delete the rectangle         r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')def left(event):        global x1,y1,x2,y2,r1    if(x1 > step): # check left edge         x1=x1-step # decrease the horizontal coordiantes        x2=x2-step        c1.delete(r1) # delete the rectangle             r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')        def up(event):        global x1,y1,x2,y2,r1    if(y1 > step): # check top edge         y1=y1-step # decrease the vertical coordinates        y2=y2-step            c1.delete(r1) # delete the rectangle             r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')   def down(event):        global x1,y1,x2,y2,r1    if(y2 < c_height-step): # check bottom edge         y1=y1+step # increase the vertical coordinates        y2=y2+step        c1.delete(r1) # delete the rectangle             r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')            b1=tk.Button(my_w,text='Left',command=lambda:left('x'))b1.grid(row=1,column=0,rowspan=2,sticky='E')b2=tk.Button(my_w,text='Up',command=lambda:up('x'))b2.grid(row=1,column=1)b3=tk.Button(my_w,text='Right',command=lambda:right('x'))b3.grid(row=1,column=2,rowspan=2,sticky='W')b4=tk.Button(my_w,text='Down',command=lambda:down('x'))b4.grid(row=2,column=1)
my_w.bind('<Right>',right)my_w.bind('<Left>',left)my_w.bind('<Up>',up)my_w.bind('<Down>',down)
my_w.mainloop()

Moving automatically in all directions

Instead of triggering the functions ( in different directions ) left(), right(), up() , down() by using buttons or arrow keys , we can use timer to trigger the functions. After reaching the edge in any direction we can call another direction function to move the item in other direction.

We are checking the edges by using one if condition, so once the edge is reached by using the else part we can call different function to change the direction.
import tkinter as tkmy_w = tk.Tk()
width,height=610,410 # set the variables c_width,c_height=width-10,height-65 # canvas width heightd=str(width)+"x"+str(height)my_w.geometry(d) 
c1 = tk.Canvas(my_w, width=c_width, height=c_height,bg='lightgreen')c1.grid(row=0,column=0,padx=5,pady=5,columnspan=3)step=10 # jump value speed=100 # delay in milli seconds , decrease the value to increase speedx1,y1=5,200x2,y2=x1+15,y1+15
r1=c1.create_rectangle(x1,y1,x2,y2,fill='red')
def right():         global x1,y1,x2,y2,r1    if (x2<(c_width-step)): # check the right edge        c1.delete(r1) # delete the rectangle         x1,x2=x1+step,x2+step # increase the horizontal coordinates                r1=c1.create_rectangle(x1, y1,x2,y2,fill='red')        c1.after(speed,right)    else:        down()def left():    global x1,y1,x2,y2,r1    if(x1>step): # check left edge         c1.delete(r1)        x1,x2=x1-step,x2-step        r1=c1.create_rectangle(x1,y1,x2,y2,fill='red')        c1.after(speed,left)    else: # edge is reached so change direction         up()  def up():    global x1,y1,x2,y2,r1    if(y1>step): # check top edge         c1.delete(r1)        y1,y2=y1-step,y2-step        r1=c1.create_rectangle(x1,y1,x2,y2,fill='red')        c1.after(speed,up)            else: # edge is reached so change direction         right()def down():    global x1,y1,x2,y2,r1    if(y2 < (c_height-step)): # check bottom edge                c1.delete(r1)        y1,y2=y1+step,y2+step        r1=c1.create_rectangle(x1,y1,x2,y2,fill='red')        c1.after(speed,down)    else: # edge is reached so move left         left()
b1=tk.Button(my_w,text='Left',command=lambda:left())b1.grid(row=1,column=0,rowspan=2,sticky='E')b2=tk.Button(my_w,text='Up',command=lambda:up())b2.grid(row=1,column=1)b3=tk.Button(my_w,text='Right',command=lambda:right())b3.grid(row=1,column=2,rowspan=2,sticky='W')b4=tk.Button(my_w,text='Down',command=lambda:down())b4.grid(row=2,column=1)
my_w.mainloop()
Tkinter Canvas Animation using Rectangles & Circles
Sin & cos curves in Canvas
Subscribe to our YouTube Channel here


Subscribe

* indicates required
Subscribe to plus2net

    plus2net.com



    Post your comments , suggestion , error , requirements etc here





    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 FORUM . Contact us
    ©2000-2024 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer