PhotoImage не отвечает на виджет масштабирования tkinter

1

У меня есть скрипт python, который позволяет пользователю открывать изображение в виджне холста tkinter. Программа распечатывает размер, который должно быть для нового изображения, но появляется только исходное изображение. Как обновить холст с новым размером.

Вот код python:

from Tkinter import * 
import tkFileDialog
from PIL import ImageTk, Image
factor = 1.0
width_org = 500
height_org = 500
mGui = Tk()
mGui.geometry("600x600")
mGui.configure(background = 'yellow')
frame = Frame(mGui, width = 400, height = 400)
frame.pack(anchor = 'nw')
frame.configure(background = 'red')
canvasframe = Canvas(frame, width = 400, height = 400, scrollregion = (-500,-500,500,500))
hbar = Scrollbar(frame,orient=HORIZONTAL)
hbar.pack(side=BOTTOM, fill = X)
hbar.configure(command= canvasframe.xview)
vbar = Scrollbar(frame,orient = VERTICAL )
vbar.pack(side=RIGHT, fill = Y)
vbar.configure(command= canvasframe.yview)
canvasframe.configure(xscrollcommand= hbar.set, yscrollcommand= vbar.set)
canvasframe.pack( expand = True, fill = BOTH)
pil_img = Image.open("rose-flower-500x500.jpg")
img = ImageTk.PhotoImage(pil_img)
def openit():
    in_path = tkFileDialog.askopenfilename()
    try:
        pil_img = Image.open(in_path)
    except IOError:
        pass
    width_org, height_org = pil_img.size
    try:
        img = ImageTk.PhotoImage(pil_img)
    except IOError:
        pass

    canvasframe.create_image(20,20, image = img)
    canvasframe.img = img
valueList = [25, 50, 100, 150, 200]
def valuecheck(value):
    newval = min(valueList, key=lambda x:abs(x-float(value)))
    scalepic.set(newval)
    factor = newval/100.0
    w = int(width_org*factor)
    h = int(height_org*factor)
    print (w, h)
    pil_img = pil_img.resize((w,h),Image.ANTIALIAS)
    img = ImageTk.PhotoImage(pil_img)
    canvasframe.create_image(20,20, image =img)
openpic = Button(mGui, text = "Open", command = openit).pack()
scalelabel = Label(mGui, text = "Resize Image").pack()
scalepic = Scale(mGui, from_=min(valueList), to=max(valueList), command=valuecheck, orient = HORIZONTAL)
scalepic.set(100)
scalepic.pack() 

mGui.mainloop()

Также, как я могу открыть новое изображение? Я думаю о цикле for и каком-то методе dispose, но я не уверен в синтаксисе.

EDIT Часть кода в классах

from Tkinter import *
import tkFileDialog
from PIL import ImageTk, Image


factor = 1.0
width_org = 500
height_org = 500
class MainApp(Frame):
    def createControls(self):
        frame = Frame(self, width = 600, height = 500)
        frame.configure(background = 'red')
        frame.pack(anchor = 'nw')
        canvasframe = Canvas(frame, width = 600, height = 500, scrollregion = (-600,-500,600,500))
        canvasframe.configure(xscrollcommand= hbar.set, yscrollcommand= vbar.set)
        canvasframe.pack(expand = True, fill = BOTH)
        hbar = Scrollbar(frame, orient=HORIZONTAL)
        hbar.pack(side=BOTTOM, fill=X)
        hbar.configure(command= canvasframe.xview)
        vbar = Scrollbar(frame, orient=VERTICAL)
        vbar.pack(side=RIGHT, fill = Y)
        vbar.configure(command= canvasframe.yview)


    def __init__(self, parent):
        Frame.__init__(self, parent, width = 800, height = 600, background = 'yellow')
        self.pack()
        self.createControls()


root = Tk()
app = MainApp(parent =root)

app.mainloop()
Теги:
image
tkinter

1 ответ

0
Лучший ответ

Вы забыли сохранить ссылку на новый PhotoImage в canvasframe.img, поэтому он получает мусор, собранный, когда valuecheck возвращается.

Кроме того, вместо создания нового изображения Canvas с помощью create_image для масштабированного изображения вам нужно просто обновить существующее через itemconfig. Для этого вам нужно сохранить номер идентификатора элемента, возвращенный create_image. Например, в openit, do

canvasframe.imgid = canvasframe.create_image(20,20, image = img)

И затем в valuecheck, после того, как вы создадите новый PhotoImage, сделайте

canvasframe.img = img
canvasframe.itemconfig(canvasframe.imgid, image=img)

Вам не нужно хранить img и imgid качестве атрибутов canvasframe, но это удобно в этом случае. Это было бы грязно, хотя если бы у вас было много вещей на холсте, которые вы должны были отслеживать. Но для более крупных программ Tkinter неплохо поместить все в один или несколько классов. Это делает вещи более организованными и доступными.

  • 0
    Ваше решение очень полезно. Я просто не уверен насчет синтаксиса для сохранения нового фотоизображения и сохранения идентификационного номера
  • 0
    @ EricLopez-Reyes Пожалуйста, смотрите мое обновление.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню