Tkinter:在画布上缩放项目 [英] Tkinter: Scaling items on a canvas

查看:26
本文介绍了Tkinter:在画布上缩放项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解画布缩放的工作原理.

以下面的代码为例.为什么绑定到鼠标滚轮的 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="horizo​​ntal", 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆