Tkinter:在画布上缩放项目 [英] Tkinter: Scaling items on a canvas
问题描述
我试图了解画布缩放的工作原理.
以下面的代码为例.为什么绑定到鼠标滚轮的 canvas.scale("all", ...)
正在缩放所有矩形而不是文本.
如何实现文本和矩形的缩放?
将 Tkinter 导入为 tk随机导入按下 = 假类示例(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="nse")self.grid_rowconfigure(0, weight=1)self.grid_columnconfigure(0, weight=1)#绘制一些矩形对于范围内的 n(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="单击并拖动以移动画布\n滚动以缩放.")# 这就是使用鼠标的原因:self.canvas.bind("", self.move_start)self.canvas.bind("", self.move_move)self.canvas.bind("", self.pressed2)self.canvas.bind("", self.move_move2)#linux滚动self.canvas.bind("", self.zoomerP)self.canvas.bind("", self.zoomerM)#windows 滚动self.canvas.bind("<MouseWheel>",self.zoomer)# Hack 使缩放在 Windows 上工作root.bind_all("<MouseWheel>",self.zoomer)#移动def move_start(self, event):self.canvas.scan_mark(event.x, event.y)def move_move(self, event):self.canvas.scan_dragto(event.x, event.y, gain=1)#移动def press2(self, event):全球压力按下 = 未按下self.canvas.scan_mark(event.x, event.y)def move_move2(self, event):如果按下:self.canvas.scan_dragto(event.x, event.y, gain=1)#windows 缩放def zoomer(self,event):如果 (event.delta > 0):self.canvas.scale("all", event.x, event.y, 1.1, 1.1)elif (event.delta <0):self.canvas.scale("all", event.x, event.y, 0.9, 0.9)self.canvas.configure(scrollregion = self.canvas.bbox("all"))#linux 缩放def zoomerP(self,event):self.canvas.scale("all", event.x, event.y, 1.1, 1.1)self.canvas.configure(scrollregion = self.canvas.bbox("all"))def zoomerM(self,event):self.canvas.scale("all", event.x, event.y, 0.9, 0.9)self.canvas.configure(scrollregion = self.canvas.bbox("all"))如果 __name__ == "__main__":根 = tk.Tk()Example(root).pack(fill="both", expand=True)root.mainloop()
文本的缩放并不是真正的"文本的缩放.这是(至少对于 Canvas
-widget)字体的改变.
来自文档:<块引用>此方法不会更改文本项的大小,但可能会移动它.
此行为也适用于图像(使用 Tkinter.Canvas.create_image(...)
创建)和窗口(使用 Tkinter.Canvas.create_window(...)
创建).正如文档将缩放定义为<块引用>.scale(tagOrId, xOffset, yOffset, xScale, yScale)
根据它们与点 P=(xOffset, yOffset) 的距离缩放所有对象.比例因子 xScale 和 yScale 基于值 1.0,这意味着没有缩放.移动由 tagOrId 选择的对象中的每个点,使其与 P 的 x 距离乘以 xScale,其 y 距离乘以 yScale.
请注意斜体部分以了解缩放的工作原理.
结束编辑
如果您想增加字体大小,您需要使用 itemconfigure
方法自行配置所有文本元素.
要以非常实用的方式实现它,您可以使用 tags
来标识所有文本元素.如果您首先获得字体大小 (itemcget
),然后根据比例因子增加它,那么增加不仅可以是绝对的,也可以是相对的.
I was trying to understand how the scaling of canvas works.
Take for example, the following code. Why is that canvas.scale("all", ...)
, which is bind to mouse wheel, is scaling all the rectangles and not the text as well.
How can I achieve scaling of text along with the rectangles?
import Tkinter as tk
import random
pressed = False
class Example(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)
#Plot some rectangles
for n in range(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.")
# 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)
#move
def move_start(self, event):
self.canvas.scan_mark(event.x, event.y)
def move_move(self, event):
self.canvas.scan_dragto(event.x, event.y, gain=1)
#move
def pressed2(self, event):
global pressed
pressed = not pressed
self.canvas.scan_mark(event.x, event.y)
def move_move2(self, event):
if pressed:
self.canvas.scan_dragto(event.x, event.y, gain=1)
#windows zoom
def zoomer(self,event):
if (event.delta > 0):
self.canvas.scale("all", event.x, event.y, 1.1, 1.1)
elif (event.delta < 0):
self.canvas.scale("all", event.x, event.y, 0.9, 0.9)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
#linux zoom
def zoomerP(self,event):
self.canvas.scale("all", event.x, event.y, 1.1, 1.1)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def zoomerM(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()
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)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.
Please note the italic part for how scaling works.
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.
这篇关于Tkinter:在画布上缩放项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!