无法调整画布上图像列表的大小

我的画布上有一个矩形和两个图像。当我通过左右拖动窗口角来调整大小时,会发生这种情况:

无法调整画布上图像列表的大小

  • 蓝色矩形的大小正确调整。
  • 红色和绿色图像的边框仅正确调整了大小。
  • 无论我如何尝试使用ImageTk.PhotoImage()重新生成红色和绿色图像,其大小都保持不变。

这是我的python代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

from PIL import Image,ImageTk

root = Tk()

images = []     # to hold the newly created image
fills = []      # associated list of fill attributes

# a subclass of Canvas for dealing with resizing of windows
class ResizingCanvas(Canvas):
    def __init__(self,parent,**kwargs):
        Canvas.__init__(self,**kwargs)

        self.bind("<Configure>",self.on_resize)
        self.height = self.winfo_reqheight()
        self.width = self.winfo_reqwidth()

    def on_resize(self,event):
        # determine the ratio of old width/height to new width/height
        wscale = float(event.width)/self.width
        hscale = float(event.height)/self.height
        # Save new values as old values
        self.width = event.width
        self.height = event.height
        # resize images
        for idx,image in enumerate(images):
            fill=fills[idx]
            dimensions = "image size: %dx%d" % (image.width(),image.height())
            events = "event size: %dx%d" % (event.width,event.height)
            neww=int(image.width()*wscale)
            newh=int(image.height()*hscale)
            image = Image.new('RGBA',(neww,newh),fill)
            image = ImageTk.PhotoImage(image)
#            images[idx] = image
        # resize the canvas 
        self.config(width=self.width,height=self.height)
        # rescale all objects with the "all" tag
        self.scale("all",wscale,hscale)

def create_rectangle(x1,y1,x2,y2,**kwargs):
    if 'alpha' in kwargs:
        alpha = int(kwargs.pop('alpha') * 255)
        fill = kwargs.pop('fill')
        fill = root.winfo_rgb(fill) + (alpha,)
        fills.append(fill)
#        print (fill)
        image = Image.new('RGBA',(x2-x1,y2-y1),fill)
        images.append(ImageTk.PhotoImage(image))
        mycanvas.create_image(x1,image=images[-1],anchor='nw')
    mycanvas.create_rectangle(x1,**kwargs)

root.title('alpha1.py')

myframe = Frame(root)
myframe.pack(fill=BOTH,expand=YES)
WinWid=1490; Winhgt=860
mycanvas = ResizingCanvas(myframe,width=WinWid,height=Winhgt,\
                          highlightthickness=0)
mycanvas.pack(fill=BOTH,expand=YES)

create_rectangle(100,100,600,fill='blue')
create_rectangle(300,300,950,700,fill='green',alpha=.5)
create_rectangle(200,500,850,820,fill='#800000',alpha=.6)
mycanvas.addtag_all("all")

root.mainloop()

注意该行:

#            images[idx] = image

如果我删除评论#,则红色和绿色图像均不会被绘制。仅出现图像边框。我认为这是关键,因为在调整大小之前,image应该等于images[idx]

如果可以回答,请记住,该项目的下一步是获取图像(或矩形)并将其移动到可调整大小的画布上。

zhb6434513 回答:无法调整画布上图像列表的大小

感谢Stovfl's comment我可以使用:

self.itemconfig(items[idx],image=image)

更改图像尺寸。不幸的是,缩放在tkinter中起作用的方式:

# rescale all objects with the "all" tag
self.scale("all",wscale,hscale)

图像没有完全填充边框,缺少一两个像素。因此我必须根据原始画布的宽度和高度生成自己的缩放因子:

# images use ratio of original width/height to new width/height
wiscale = float(event.width)/self.startw
hiscale = float(event.height)/self.starth

最后,为了防止垃圾收集器删除我将其重新分配到列表中的调整大小的图像,

resized[idx]=image  # stop garbage collector from removing image

TL; DR

如果您想在自己的项目中使用它,这里是完整的Python脚本:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

from PIL import Image,ImageTk

root = Tk()

images = []     # to hold the newly created image
resized = []    # Resized images
fills = []      # associated list of fill attributes
items = []      # associated list of canvass item tags / ids

# a subclass of Canvas for dealing with resizing of windows
class ResizingCanvas(Canvas):
    def __init__(self,parent,**kwargs):
        Canvas.__init__(self,**kwargs)

        self.bind("<Configure>",self.on_resize)
        self.height = self.winfo_reqheight()
        self.width = self.winfo_reqwidth()
        self.startw = self.width
        self.starth = self.height

    def on_resize(self,event):
        # determine the ratio of previous width/height to new width/height
        wscale = float(event.width)/self.width
        hscale = float(event.height)/self.height
        # Save new values as old values
        self.width = event.width
        self.height = event.height
        # images use ratio of original width/height to new width/height
        wiscale = float(event.width)/self.startw
        hiscale = float(event.height)/self.starth

        # resize images
        for idx,image in enumerate(images):
            fill=fills[idx]
            neww=int(image.width()*wiscale)
            newh=int(image.height()*hiscale)
            image = Image.new('RGBA',(neww,newh),fill)
            image = ImageTk.PhotoImage(image)
            self.itemconfig(items[idx],image=image)
            resized[idx]=image  # stop garbage collector from removing image

        # resize the canvas 
        self.config(width=self.width,height=self.height)
        # rescale all objects with the "all" tag
        self.scale("all",hscale)

def create_rectangle(x1,y1,x2,y2,**kwargs):
    if 'alpha' in kwargs:
        alpha = int(kwargs.pop('alpha') * 255)
        fill = kwargs.pop('fill')
        fill = root.winfo_rgb(fill) + (alpha,)
        fills.append(fill)
        image = Image.new('RGBA',(x2-x1,y2-y1),fill)
        images.append(ImageTk.PhotoImage(image))
        item=mycanvas.create_image(x1,image=images[-1],anchor='nw')
        items.append(item)
    mycanvas.create_rectangle(x1,**kwargs)

root.title('alpha1.py')

myframe = Frame(root)
myframe.pack(fill=BOTH,expand=YES)
WinWid=1490; WinHgt=860
mycanvas = ResizingCanvas(myframe,width=WinWid,height=WinHgt,\
                          highlightthickness=0)
mycanvas.pack(fill=BOTH,expand=YES)

create_rectangle(100,100,600,fill='blue')
create_rectangle(300,300,950,700,fill='green',alpha=.5)
create_rectangle(200,500,850,820,fill='#800000',alpha=.6)
mycanvas.addtag_all("all")
for image in images:
    resized.append(image)

root.mainloop()
本文链接:https://www.f2er.com/2920236.html

大家都在问