Tkinter: Scaling Items On A Canvas
Solution 1:
The Scaling of text is not "really" a scaling of text. It is (at least with the Canvas
-widget) a change of font.
From the documentation :
This method will not change the size of a text item, but may move it.
Edit:
This behaviour also applies to images (created with Tkinter.Canvas.create_image(...)
) and windows (created with Tkinter.Canvas.create_window(...)
). As the documentation defines scaling as
.scale(tagOrId, xOffset, yOffset, xScale, yScale)Please note the italic part for how scaling works.Scale all objects according to their distance from a point P=(xOffset, yOffset). The scale factors xScale and yScale are based on a value of 1.0, which means no scaling. Every point in the objects selected by tagOrId is moved so that its x distance from P is multiplied by xScale and its y distance is multiplied by yScale.
End Edit
If you want to perform an increase of font-size you need to configure all the text elements by yourself using the itemconfigure
method.
To Implement it in a very functional way you could use tags
to identify all text elements. Increasing can happen not only absolute but also relatively if you first get the fontsize (itemcget
) and then increase it depending on scale factor.
Solution 2:
I know this post is old but I solved a similar question so I thought I would post a solution for the problem as well.
The idea is to add a tag to the text item and then reconfigure it each time the zoomer is called. Note, this solution does not change the linux zoom (zoomerP)
import tkinter as tk
import random
pressed = FalseclassExample(tk.Frame):
def__init__(self, root):
tk.Frame.__init__(self, root)
self.canvas = tk.Canvas(self, width=400, height=400, background="bisque")
self.xsb = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview)
self.ysb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.ysb.set, xscrollcommand=self.xsb.set)
self.canvas.configure(scrollregion=(0,0,1000,1000))
self.xsb.grid(row=1, column=0, sticky="ew")
self.ysb.grid(row=0, column=1, sticky="ns")
self.canvas.grid(row=0, column=0, sticky="nsew")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.fontSize = 10#Plot some rectanglesfor n inrange(50):
x0 = random.randint(0, 900)
y0 = random.randint(50, 900)
x1 = x0 + random.randint(50, 100)
y1 = y0 + random.randint(50,100)
color = ("red", "orange", "yellow", "green", "blue")[random.randint(0,4)]
self.canvas.create_rectangle(x0,y0,x1,y1, outline="black", fill=color, activefill="black", tags=n)
self.canvas.create_text(50,10, anchor="nw", text="Click and drag to move the canvas\nScroll to zoom.", font = ("Helvetica", int(self.fontSize)), tags="text")
# This is what enables using the mouse:
self.canvas.bind("<ButtonPress-1>", self.move_start)
self.canvas.bind("<B1-Motion>", self.move_move)
self.canvas.bind("<ButtonPress-2>", self.pressed2)
self.canvas.bind("<Motion>", self.move_move2)
#linux scroll
self.canvas.bind("<Button-4>", self.zoomerP)
self.canvas.bind("<Button-5>", self.zoomerM)
#windows scroll
self.canvas.bind("<MouseWheel>",self.zoomer)
# Hack to make zoom work on Windows
root.bind_all("<MouseWheel>",self.zoomer)
#movedefmove_start(self, event):
self.canvas.scan_mark(event.x, event.y)
defmove_move(self, event):
self.canvas.scan_dragto(event.x, event.y, gain=1)
#movedefpressed2(self, event):
global pressed
pressed = not pressed
self.canvas.scan_mark(event.x, event.y)
defmove_move2(self, event):
if pressed:
self.canvas.scan_dragto(event.x, event.y, gain=1)
#windows zoomdefzoomer(self,event):
if (event.delta > 0):
self.canvas.scale("all", event.x, event.y, 1.1, 1.1)
self.fontSize = self.fontSize * 1.1elif (event.delta < 0):
self.canvas.scale("all", event.x, event.y, 0.9, 0.9)
self.fontSize = self.fontSize * 0.9
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
for child_widget in self.canvas.find_withtag("text"):
self.canvas.itemconfigure(child_widget, font=("Helvetica", int(self.fontSize)))
print(self.fontSize)
#linux zoomdefzoomerP(self,event):
self.canvas.scale("all", event.x, event.y, 1.1, 1.1)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
defzoomerM(self,event):
self.canvas.scale("all", event.x, event.y, 0.9, 0.9)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
Post a Comment for "Tkinter: Scaling Items On A Canvas"