Another method to move canvas objects?

Viewed 1125

I would like to know if besides canvas.move(), there is another method that allows to change the position of an object inside the canvas. I would much rather setting a specific coordinations than moving the object.

2 Answers

If you want to move an object on the Canvas, try this: Try this:

# In Python 3.8 and greater you can use this:
# `<tk.Canvas>.moveto(object, new_x, new_y)`
# like what @JacksonPro pointed out.
# but I am using python 3.7 so I am using this:

import tkinter as tk

def abs_move(self, _object, new_x, new_y):
    # Get the current object position
    x, y, *_ = self.bbox(_object)
    # Move the object
    self.move(_object, new_x-x, new_y-y)
# Monkey patch the `abs_move` method
tk.Canvas.abs_move = abs_move


"""
Testing script:
"""
# Moves the square to x=300
def move_square():
    canvas.abs_move(square, 300, 0)

root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=200, bg="cyan")
canvas.pack()
button = tk.Button(root, text="Move square to x=300", command=move_square)
button.pack()

square = canvas.create_rectangle(100, 0, 200, 100, fill="black")

root.mainloop()

Another way is just to just call the tcl interpreter directly. Taken from here - @martineau found it.

# Works python 3.7 and greater

import tkinter as tk

def moveto(self, tagOrId, xPos, yPos):
    # Taken from https://bugs.python.org/issue23831
    """Move the items given by tagOrId in the canvas coordinate  
    space so that the first coordinate pair of the bottommost 
    item with tag tagOrId is located at position (xPos,yPos). 
    xPos and yPos may be the empty string, in which case the        
    corresponding coordinate will be unchanged. All items matching
    tagOrId remain in the same positions relative to each other.    
    This command returns an empty string. 
    """
    return self.tk.call(self._w, "moveto", tagOrId, xPos, yPos)
tk.Canvas.moveto = moveto


"""
Testing script:
"""
# Moves the square to x=300
def move_square():
    canvas.moveto(square, 300, 0)

root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=200, bg="cyan")
canvas.pack()
button = tk.Button(root, text="Move square to x=300", command=move_square)
button.pack()

square = canvas.create_rectangle(100, 0, 200, 100, fill="black")

root.mainloop()

If you want to move the actual canvas, try this:

import tkinter as tk


class MovableCanvas(tk.Frame):
    def __init__(self, master, bg=None, canvas_bg=None, canvas_width=None,
                 canvas_height=None, **kwargs):
        super().__init__(master, bg=bg, **kwargs)
        self.canvas = tk.Canvas(self, bg=canvas_bg, width=canvas_width,
                                height=canvas_height)
        self.canvas.place(x=0, y=0)

    def move_canvas(self, new_x, new_y):
        self.canvas.place(x=new_x, y=new_y)


# Moves the whole Canvas to x=300
def move_square():
    canvas.move_canvas(300, 0)

root = tk.Tk()
canvas = MovableCanvas(root, width=400, height=200, canvas_width=100,
                       canvas_height=100, bg="cyan", canvas_bg="orange")
canvas.pack()
button = tk.Button(root, text="Move square to x=300", command=move_square)
button.pack()

root.mainloop()

here is the option with the frame:

frame = Frame(root)
frame.place(x=60, y=60)
canvas = Canvas(frame, width=500, height=100)
canvas.pack()
Related