I'd like to create a search/finder tool for a map displayed in a canvas. I'd like the canvas to shift to the item when the user clicks find. How can I shift the view of the canvas to that item, preferably with zooming to fill the screen with that item?
In trying to find a solution I've explored the canvas.xview_moveto which seems like the right function but it looks like the input for that is the
...FRACTION of the total width of the canvas (to be made) off-screen to the left".
I can probably write some janky code to use that but it would be quite inelegant.
Likewise, I've looked at co-opting the scan_mark and scan_dragto functions but I'm also using those for zooming and it's producing odd results.
What I'd like is a function that allows me to input the bounds of a view (xmin, xmax, ymin, ymax) and snap to that. Is there any function that let's me do that?
Reproducible example code. I hard-coded it to always go to the third circle, to skip the item input part to reduce the size of the example code.
items = [
(25, 25),
(25, 50),
(25, 75),
(25, 100)
]
circle_rad = 10
def go_to_third():
# desired code
# canvas.set_x(items[2][0])
# canvas.set_y(items[2][1])
# canvas.set_width(circle_rad * 2, keep_xy_ratio=True)
pass # to make this run/compile
def do_pan(event):
canvas.scan_mark(event.x, event.y)
def do_zoom(event):
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
factor = 1.001 ** event.delta
canvas.scale(tk.ALL, x, y, factor, factor)
# set up canvas
root = tk.Tk()
window = tk.Frame(root)
window.pack()
search_button = tk.Button(window, text="go to 3rd item", command=go_to_third)
search_button.grid(row=0, column=0)
canvas = tk.Canvas(window, bg='lightgrey')
canvas.grid(row=1, column=0)
canvas.bind("<ButtonPress-1>", do_pan)
canvas.bind("<B1-Motion>", lambda event: canvas.scan_dragto(event.x, event.y, gain=1))
canvas.bind("<MouseWheel>", do_zoom)
item_ids = []
for x, y in items:
item_ids.append(canvas.create_oval(
x - circle_rad,
y - circle_rad,
x + circle_rad,
y + circle_rad
))
root.mainloop()
The code above produces the following:
Clicking the "go to 3rd item" button should produce the following:

