您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

使用Tkinter画布小部件添加放大和缩小?

使用Tkinter画布小部件添加放大和缩小?

据我所知,内置的Tkinter Canvas类缩放不会自动缩放图像。如果无法使用自定义窗口小部件,则可以缩放原始图像,并在调用缩放功能时将其替换在画布上。

下面的代码片段可以合并到您的原始类中。它执行以下操作:

(已 )代码

class GUI:
    def __init__(self, root):

        # ... omitted rest of initialization code

        self.canvas.config(scrollregion=self.canvas.b@R_153_2419@(ALL))
        self.scale = 1.0
        self.orig_img = Image.open(File)
        self.img = None
        self.img_id = None
        # draw the initial image at 1x scale
        self.redraw()

        # ... rest of init, bind buttons, pack frame

    def zoom(self,event):
        if event.num == 4:
            self.scale *= 2
        elif event.num == 5:
            self.scale *= 0.5
        self.redraw(event.x, event.y)

    def redraw(self, x=0, y=0):
        if self.img_id:
            self.canvas.delete(self.img_id)
        iw, ih = self.orig_img.size
        size = int(iw * self.scale), int(ih * self.scale)
        self.img = ImageTk.PhotoImage(self.orig_img.resize(size))
        self.img_id = self.canvas.create_image(x, y, image=self.img)

        # tell the canvas to scale up/down the vector objects as well
        self.canvas.scale(ALL, x, y, self.scale, self.scale)

我做了一些不同比例的测试,发现resize / create_image正在使用大量内存。我在具有32GB RAM的Mac Pro上使用540x375 JPEG进行了测试。这是用于不同比例因子的内存:

 1x  (500,     375)      14 M
 2x  (1000,    750)      19 M
 4x  (2000,   1500)      42 M
 8x  (4000,   3000)     181 M
16x  (8000,   6000)     640 M
32x  (16000, 12000)    1606 M
64x  (32000, 24000)  ...  
reached around ~7400 M and ran out of memory, EXC_BAD_ACCESS in _memcpy

鉴于以上所述,一种更有效的解决方案可能是确定将在其中显示图像的视口的大小,围绕鼠标坐标中心计算裁剪矩形,使用rect裁剪图像,然后仅缩放裁剪的部分。这应该使用常量内存来存储临时图像。否则,您可能需要使用第三方Tkinter控件来为您执行此裁剪/窗口缩放。

工作但过分简化的裁剪逻辑,只是为了让您入门:

    def redraw(self, x=0, y=0):
        if self.img_id: self.canvas.delete(self.img_id)
        iw, ih = self.orig_img.size
        # calculate crop rect
        cw, ch = iw / self.scale, ih / self.scale
        if cw > iw or ch > ih:
            cw = iw
            ch = ih
        # crop it
        _x = int(iw/2 - cw/2)
        _y = int(ih/2 - ch/2)
        tmp = self.orig_img.crop((_x, _y, _x + int(cw), _y + int(ch)))
        size = int(cw * self.scale), int(ch * self.scale)
        # draw
        self.img = ImageTk.PhotoImage(tmp.resize(size))
        self.img_id = self.canvas.create_image(x, y, image=self.img)
        gc.collect()
其他 2022/1/1 18:25:45 有593人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶