I'm trying to add support for zooming in and out inside a Canvas widget, containing both text element (created using create_text
) and non-text elements, such as rectangles (created with create_rectangle
), etc.
So far, I made the following MRE using both part of this answer and this one:
import tkinter as tk
from tkinter.font import Font
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=400)
canvas.pack()
font = Font(family="Arial", size=10)
fontsize = 10
# Add elements to canvas
rectangle = canvas.create_rectangle(100, 100, 300, 200, fill='red')
oval = canvas.create_oval(150, 150, 250, 250, fill='blue')
text = canvas.create_text(200, 175, text="Hello", font=font)
def do_zoom(event):
global fontsize
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
factor = 1.001 ** event.delta
if (event.delta > 0):
fontsize *= 1.1
font.configure(size=int(fontsize))
elif (event.delta < 0):
fontsize *= 0.9
font.configure(size=int(fontsize))
canvas.scale("all", x, y, factor, factor)
canvas.bind("<MouseWheel>", do_zoom)
canvas.bind('<ButtonPress-1>', lambda event: canvas.scan_mark(event.x, event.y))
canvas.bind("<B1-Motion>", lambda event: canvas.scan_dragto(event.x, event.y, gain=1))
root.mainloop()
This seems to work, but has one or two issues:
- Once the font size get to
0
or0.0???
in floats (happen when zooming out), the font size doesn't match with the actual visual size of the font, as it seems to be fixed in a higher size (can be seen on this gif here) - When zooming in and out fast enough, repeatedly, a discrepancy can be seen on the font size on previous mousewheel scrolling, and the next one (can be seen by printing the font size).
In short, I'm wondering if there is a way, either to fix the above (and the reasons for them happening, aside from my own conjecture) or if there is a better way to handle this.