Python PIL Изображение в автоматическом изменении метки

Я пытаюсь сделать виджет для хранения изображения, которое будет автоматически изменяться в соответствии с его контейнером, например, если оно упаковано непосредственно в окно, а затем расширение этого окна расширит изображение.

У меня есть некоторый код, который является полуфункциональным, но мне пришлось добавить пару констант в одну из подпрограмм, чтобы предотвратить автоматическое изменение размера автозапуска (заставляя его продолжать расти в размере)

Я уверен, что причина этого связана с внутренними дополнениями / границами виджетов, но даже пытаясь принять это во внимание, я получаю эту проблему.

Я использую python 3.3.2 и PIL 1.1.7 на 64-битном Windows 7, мой код следующий:

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, **kwargs): tix.Label.__init__(self, parent, **kwargs) self.bind("<Configure>", self._resize_binding) self.maxupdate = maxupdate self.update_after_id = None self.photo = None self.image = None if picture: self.set_picture(picture) def _resize_binding(self, event): if self.photo: if not self.maxupdate: self.load_picture() else: if not self.update_after_id: 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 self.image = ImageTk.PhotoImage(Resize_Image(self.photo, ( self.winfo_width()-int(self.cget("bd"))-1, self.winfo_height()-int(self.cget("bd"))-1))) # here is where I added the constants ^^^ # but even using cget to get the border size I have had to add to this # to prevent the resize loop, and when using other widget styles #(raised etc) this problem persists 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() if __name__ == "__main__": test = Pict_Frame(bg="grey", bd=2, relief="raised", maxupdate=2, # allows problem to be easily seen picture="image.jpg") test.pack(fill="both", expand=True) test.master.mainloop() 

когда я применяю другие стили, такие как более толстая граница (10px), возникает эта проблема изменения размера, показывающая, что константы действительно не решают проблему.
так есть ли какой-либо метод, чтобы получить только пространство внутри виджета, а не его запрошенный размер?

One Solution collect form web for “Python PIL Изображение в автоматическом изменении метки”

Я считаю, что теперь я решил это, но для обеспечения точных результатов на самом деле требуется гораздо больше испытаний с различными параметрами. Код, который я использую для проверки этого, выглядит следующим образом:

 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() 

и мои тестовые примеры:

 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() 

Единственная проблема, с которой я столкнулся с этим кодом, заключается в том, что при использовании виджета в полноэкранном приложении переопределение не работает по назначению, когда используется метод сетки и устанавливается вес правого столбца на 1 ( с изображением виджета), а левый столбец (пустой) до 1, правый столбец заканчивается тем, что занимает около 2 / 3rds ширину экрана.

Я подозреваю, что это связано с явным определением размера изображения, которое затем делает его более широким, что означает, что менеджер геометрии хочет сделать его еще более широким (до бесконечности), пока не достигнет некоторого равновесия. Но если кто-то может пролить свет на это (или даже на решение), это будет оценено.

  • Как получить холст tkinter для динамического изменения размера окна?
  • Tkinter и потоки
  • py2exe дает RuntimeError: слишком рано создавать образ
  • Нет отображаемого имени и переменной $ DISPLAY среды с помощью tkinter через ssh
  • всплывающее окно tkinter и обработка текста для автозаполнения
  • Как создать прямо исполняемый кросс-платформенный графический интерфейс с помощью Python?
  • Использование переменной from entry / button в другой функции в Tkinter
  • Прозрачность изображения Tkinter
  • Как получить строку и столбец конечной позиции текста в Tkinter?
  • Функция обратного вызова tkinter с переменным параметром
  • Python 2.7.9 Mac OS 10.10.3 Сообщение «setCanCycle: устарело. Вместо этого используйте setCollectionBehavior вместо "
  •  
    Interesting Posts for Van-Lav

    Выполнение математики в списке в python

    Запустите Python unittest, чтобы при печати ничего не печаталось, только AssertionError ()

    Как инвертировать цвета изображения с помощью PIL (Python-Imaging)?

    Есть еще web.py для python3?

    python BeautifulSoup get select.value не текст

    Должен ли я использовать «я» для определения переменных / объектов класса instanced, которые мне не нужно будет получать извне?

    Python: получить имя экземпляра класса?

    Эффективный способ чтения определенного номера строки файла. (БОНУС: Pizon Manual Misprint)

    насмешливое соединение сокета в Python

    Ошибка Django annotate () AttributeError: объект CharField не имеет атрибута 'resolve_expression'

    Автоматизация Python Win32Gui – отправьте WM_COPYDATA для получения данных из BSPlayer

    Как создать страницу 404?

    пытаясь отобразить изображение, извлеченное из ссылки, размещенной на сайте

    Python / Django импортирует неправильный модуль (относительный, когда он должен быть абсолютным)

    Загрузите файл через гиперссылку в PhantomJS, используя Selenium

    Python - лучший язык программирования в мире.