I place my text, entry and buttons in the same way based on the image width as seen in the code. When I now make the window bigger than the image width, then the buttons start moving like they use the left side of the window as a reference point while the text and entry still use the image corner as the reference point. What is the reason for this behavior and how to prevent it?
When increasing the window width, only the buttons use the new window size as new reference. The text and entry have the image corner as a reference.
edit: Minimum code example of the behavior
import tkinter as tk
from PIL import Image, ImageTk
# random pil image
image = Image.new('RGB', (800, 600), color = 'red')
img_shape = image.size
root = tk.Tk()
canvas = tk.Canvas(root, width=img_shape[0], height=img_shape[1] + 50)
tk_image = ImageTk.PhotoImage(image=image)
canvas.create_image(0, 0, anchor='nw', image=tk_image)
canvas.pack()
depth_min_entry = tk.Label(canvas, text="right")
depth_min_entry.place(x=img_shape[0] - 65, y=img_shape[1] + 5, height=20, width=50, anchor='ne')
depth_min_entry = tk.Entry(canvas, width=6)
depth_min_entry.place(x=img_shape[0] - 10, y=img_shape[1] + 5, height=20, width=50, anchor='ne')
depth_min_entry.insert(0, 5)
camera_info = tk.Label(canvas, text=f"left")
camera_info.place(x=10, y=img_shape[1] + 5, height=20, width=50, anchor='nw')
update_button = tk.Button(root, text="b right")
update_button.place(x=img_shape[0] - 10, y=img_shape[1] + 25, height=20, width=100, anchor='ne')
prev_button = tk.Button(root, text="b left")
prev_button.place(x=10, y=img_shape[1] + 25, height=20, width=100, anchor='nw')
root.mainloop()
place
uses coordinates relative to the parent of the widget. Since your widgets have different parents, they could have different origins when using place
.
Since the label and entry is in the canvas, the coordinates will be relative to the canvas. You use pack
to put the canvas in the root window and by default pack
centers widgets along a side (in this case the top). So, when you make the window bigger the canvas moves inward and the widgets inside of the canvas also move. However, widgets outside of the canvas don't move since they are relative to the root window.
You can prevent this in many different ways. One simple solution is to use the in_
parameter so that the widgets in the root are placed relative to the canvas.
update_button.place(..., in_=canvas)
prev_button.place(..., in_=canvas)
Another solution is to make the two buttons children of the canvas so that everything is relative to the canvas.
Another third solution is to create a frame for the buttons, and use appropriate pack
options for it as well. That would give both the canvas and the frame for the buttons.
I would argue that the best solution is to not use place
at all. Instead, consider using grid
in this particular case since you are in effect laying things out in a grid.