EN VI

Python - tkinter canvas.coords() and canvas.moveto() having different coordinates?

2024-03-10 21:00:07
How to Python - tkinter canvas.coords() and canvas.moveto() having different coordinates

I tried the following script, in a canvas that fills the window:

import tkinter as tk
from PIL import Image, ImageTk
from time import *

root = tk.Tk()
root.geometry("500x500")
canvas = tk.Canvas(root)
canvas.pack()

def fill(event):
    canvas.config(width = root.winfo_width(), height = root.winfo_height())
root.bind("<Configure>", fill)

img = Image.open("CO2.png")
imgtk = ImageTk.PhotoImage(img)
item = canvas.create_image(15, 15, image = imgtk)
while True:
    canvas.moveto(item, canvas.coords(item)[0], canvas.coords(item)[1])
    root.update()
    sleep(0.5)

This should do nothing, because it's moving an item to where it already is. But in practice, this moves the image towards the positive x and y direction, which means the coordinates from canvas.coords() is slightly off and do not correspond to canvas.moveto().

Here's the used image:

enter image description here

What is happening here?

Solution:

That behavior is documented and you observing the functionality as it is intended.
canvas.coords(item) will return where the item currently is.
canvas.moveto(item, *coord_list) will place the item so that the upper left corner is below and next to the coordinates in *coord_list.

Compare the documentation of coords with moveto.

If no coordinates are specified, this command returns a list whose elements are the coordinates of the item named by tagOrId.

and

Move the items given by tagOrId in the canvas coordinate space so that the first coordinate pair (the upper-left corner of the bounding box) of the first item (the lowest in the display list) with tag tagOrId is located at position (xPos,yPos)

This small snippet code demonstrate your experience:

import tkinter as tk

def test(event):
    cnvs.moveto(rect, *cnvs.coords(rect)[0:-2])

root = tk.Tk()
cnvs = tk.Canvas(root, highlightthickness=0)
cnvs.pack()
rect = cnvs.create_rectangle(0,0,50,50, fill='red')
print(cnvs.coords(rect))
root.bind('<1>', test)
root.mainloop()

while changing the function test to the following will solve the issue:

def test(event):
    coords = [coordinate-1 for coordinate in cnvs.coords(rect)[0:-2]]
    cnvs.moveto(rect, *coords)
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login