Ich glaube, ich habe das jetzt gelöst, aber es braucht wirklich viel mehr Tests mit verschiedenen Parametern, um genaue Ergebnisse zu gewährleisten. Der Code, den ich verwenden zu testen ist dies wie folgt:
from tkinter import tix
from PIL import Image, ImageTk
def Resize_Image(image, maxsize):
r1 = image.size[0]/maxsize[0] # width ratio
r2 = image.size[1]/maxsize[1] # height ratio
ratio = max(r1, r2)
newsize = (int(image.size[0]/ratio), int(image.size[1]/ratio)) # keep image aspect ratio
image = image.resize(newsize, Image.ANTIALIAS)
return image
class Pict_Frame(tix.Label):
def __init__(self, parent=None, picture=None, maxupdate=None, imagesize=None, **kwargs):
tix.Label.__init__(self, parent, **kwargs)
self.bind("<Configure>", self._resize_binding)
self.maxupdate = maxupdate
self.imagesize = imagesize
self.update_after_id = None # used for update rate limiting
self.photo = None # used to store raw image from file for later use
self.image = None # used for reference to the resized image
if imagesize:
self.photo=Image.new("RGB", (1,1)) # create empty image to insert
self.image=ImageTk.PhotoImage(self.photo) # create instance of image for PIL
self.configure(image=self.image)
self.configure(width=imagesize[0], height=imagesize[1]) # not label uses pixels for size, set size passed in
if picture:
self.set_picture(picture) # we have a picture so load it now
def _resize_binding(self, event):
if self.photo: # we have a picture
if not self.maxupdate: # no rate limiting
self.load_picture()
else:
if not self.update_after_id: # if we're not waiting then queue resize
self.update_after_id = self.after(int(1000/self.maxupdate), self.load_picture)
def load_picture(self):
if self.photo:
if self.update_after_id:
self.update_after_id = None
if (self.winfo_width() > 1) and (self.winfo_height() > 1): # prevent updates before widget gets sized
bd = self.cget("bd") # get the border width
if type(bd) != int: # if there was no border set we get an object back
pad = 4 # set this explicitly to avoid problems
else:
pad = int(bd*2) # we have a border both sides, so double the retrieved value
newsize = (self.winfo_width()-pad, self.winfo_height()-pad)
elif self.imagesize: # only use the passed in image size if the widget has not rendered
newsize = self.imagesize
else:
return # widget not rendered yet and no size explicitly set, so break until rendered
self.image = ImageTk.PhotoImage(Resize_Image(self.photo, newsize))
self.configure(image=self.image)
def set_picture(self, filename):
with open(filename, mode="rb") as file:
self.photo = Image.open(file)
self.photo.load() # load image into memory to allow resizing later without file access
self.load_picture()
und meine Testfälle waren:
import os
path = "E:\imagefolder"
images = []
ind = 0
for item in os.listdir(path): # get a fully qualified list of images
if os.path.isdir(os.path.join(path, item)):
if os.path.isfile(os.path.join(path, item, "thumb.jpg")):
images.append(os.path.join(path, item, "thumb.jpg"))
def callback():
global ind
ind += 1
if ind >= len(images):
ind = 0
pict.set_picture(images[ind])
ignore_test_cases = []
if 1 not in ignore_test_cases:
print("test case 1: - no border no set size")
root = tix.Tk()
tix.Button(root, text="Next Image", command=callback).pack()
pict = Pict_Frame(parent=root, bg="grey",
maxupdate=2, # allows problem to be easily seen
picture=images[ind])
pict.pack(fill="both", expand=True)
tix.Button(root, text="Next Image", command=callback).pack()
root.mainloop()
if 2 not in ignore_test_cases:
print("test case 2: - small border no set size")
root = tix.Tk()
tix.Button(root, text="Next Image", command=callback).pack()
pict = Pict_Frame(parent=root, bg="grey", bd=2, relief="raised",
maxupdate=2,
picture=images[ind])
pict.pack(fill="both", expand=True)
tix.Button(root, text="Next Image", command=callback).pack()
root.mainloop()
if 3 not in ignore_test_cases:
print("test case 3: - large border no set size")
root = tix.Tk()
tix.Button(root, text="Next Image", command=callback).pack()
pict = Pict_Frame(parent=root, bg="grey", bd=10, relief="raised",
maxupdate=2,
picture=images[ind])
pict.pack(fill="both", expand=True)
tix.Button(root, text="Next Image", command=callback).pack()
root.mainloop()
if 4 not in ignore_test_cases:
print("test case 4: - no border with set size")
root = tix.Tk()
tix.Button(root, text="Next Image", command=callback).pack()
pict = Pict_Frame(parent=root, bg="grey",
maxupdate=2,
imagesize=(256,384),
picture=images[ind])
pict.pack(fill="both", expand=True)
tix.Button(root, text="Next Image", command=callback).pack()
root.mainloop()
if 5 not in ignore_test_cases:
print("test case 5: - small border with set size")
root = tix.Tk()
tix.Button(root, text="Next Image", command=callback).pack()
pict = Pict_Frame(parent=root, bg="grey", bd=2, relief="raised",
maxupdate=2,
imagesize=(256,384),
picture=images[ind])
pict.pack(fill="both", expand=True)
tix.Button(root, text="Next Image", command=callback).pack()
root.mainloop()
if 6 not in ignore_test_cases:
print("test case 6: - large border with set size")
root = tix.Tk()
tix.Button(root, text="Next Image", command=callback).pack()
pict = Pict_Frame(parent=root, bg="grey", bd=10, relief="raised",
maxupdate=2,
imagesize=(256,384),
picture=images[ind])
pict.pack(fill="both", expand=True)
tix.Button(root, text="Next Image", command=callback).pack()
root.mainloop()
if 10 not in ignore_test_cases:
print("test case fullscreen: - small border no set size, in fullscreen window with expansion set up")
root = tix.Tk()
root.state("zoomed")
root.grid_columnconfigure(1, weight=2)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(2, weight=1)
tix.Button(root, text="Next Image", command=callback).grid(column=2, row=1, sticky="nesw")
pict = Pict_Frame(parent=root, bg="grey",# bd=10, relief="raised",
maxupdate=2,
picture=images[ind])
pict.grid(column=2, row=2, sticky="nesw")
tix.Button(root, text="Next Image", command=callback).grid(column=2, row=3, sticky="nesw")
root.mainloop()
if 11 not in ignore_test_cases:
print("test case fullscreen: - small border no set size, in fullscreen window with expansion set up")
root = tix.Tk()
root.state("zoomed")
root.grid_columnconfigure(1, weight=2)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(1, weight=1)
frame = tix.Frame(root)
frame.grid(column=2, row=1, sticky="nesw")
frame.grid_columnconfigure(1, weight=1)
frame.grid_rowconfigure(2, weight=1)
tix.Button(frame, text="Next Image", command=callback).grid(column=1, row=1, sticky="nesw")
pict = Pict_Frame(parent=frame, bg="grey",# bd=10, relief="raised",
maxupdate=2,
picture=images[ind])
pict.grid(column=1, row=2, sticky="nesw")
tix.Button(frame, text="Next Image", command=callback).grid(column=1, row=3, sticky="nesw")
root.mainloop()
Das einzige Problem, das ich mit diesem Code gehabt haben, ist, dass, wenn ich bin mit dem Widget in Bei einer Vollbildanwendung funktioniert die Größenanpassung nicht wie vorgesehen, wenn Sie die Rastermethode verwenden und die Gewichtung der rechten Spalte auf 1 (mit dem Bild-Widget) und die linke Spalte (leer) auf 1, die rechte Spalte, setzen endet mit ca. 2/3 der Breite des Bildschirms.
Ich vermute, dies liegt an der expliziten Einstellung der Größe des Bildes, was es dann breiter macht, was bedeutet, dass der Geometrie-Manager es immer noch erweitern möchte (ad infinitum), bis es ein Gleichgewicht erreicht. Aber wenn jemand dieses Licht (oder auch nur eine Lösung) beleuchten kann, würde es geschätzt werden.