我在画布上有一个矩形和两个图像。当我通过左右拖动窗口角来调整大小时,会发生这种情况:
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,parent,**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",0,0,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, y1, image=images[-1], anchor='nw')
mycanvas.create_rectangle(x1, y1, x2, y2, **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, 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]
。
如果您能回答,请记住,该项目的下一步是获取图像(或矩形)并将其在可调整大小的画布上移动。
感谢Stovfl's comment我可以使用:
self.itemconfig(items[idx], image=image)
更改图像的尺寸。不幸的是,缩放在tkinter中起作用的方式:
# rescale all objects with the "all" tag
self.scale("all",0,0,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
这里是完整的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,parent,**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",0,0,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)
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
images.append(ImageTk.PhotoImage(image))
item=mycanvas.create_image(x1, y1, image=images[-1], anchor='nw')
items.append(item)
mycanvas.create_rectangle(x1, y1, x2, y2, **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, 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()