Trying to Load an Image with Dialogue Box in Python and Display it in a Layer - PYTHON 3.4 using Tkinter and PIL -
i trying make simple photo editor. got functions editing photos. trying make nice gui. when user presses file>open, open dialogue box comes , can choose image. want image load inside of layer in gui.
here code far: p.s. when put code inside open_img function outise function, works, when put inside function, no image loads
import os tkinter import * import tkinter.messagebox pil import image, imagetk tkinter.filedialog import askopenfilename def g_quit(): mexit=tkinter.messagebox.askyesno(title="quit", message="are sure?") if mexit>0: mgui.destroy() return #open menu def open_img(): file = tkinter.filedialog.askopenfilename(initialdir='d:/users/') w_box = 500 h_box = 500 pil_image = image.open(file) w, h = pil_image.size pil_image_resized = resize(w, h, w_box, h_box, pil_image) # wr, hr = pil_image_resized.size tk_image = imagetk.photoimage(pil_image_resized) label2.config(image=tk_image, width=w_box, height=h_box) def resize(w, h, w_box, h_box, pil_image): ''' resize pil_image object fit box of size w_box times h_box, retain aspect ratio ''' f1 = 1.0*w_box/w # 1.0 forces float division in python2 f2 = 1.0*h_box/h factor = min([f1, f2]) #print(f1, f2, factor) # test # use best down-sizing filter width = int(w*factor) height = int(h*factor) return pil_image.resize((width, height), image.antialias) mgui = tk() mgui.title('photo filters') mgui.geometry('650x500') mgui.resizable(0, 0) #disable resizeability photoframe = frame(mgui, bg="orange", width=500, height=500) photoframe.pack(side=left) filtersframe = frame(mgui, bg="yellow", width=150, height=500) filtersframe.pack(side=left, fill=y) label2 = label(photoframe) #create buttons possible filters negative_btn = button(filtersframe, text="negative") negative_btn.pack() weighted_grayscale_btn = button(filtersframe, text="weighted grayscale") weighted_grayscale_btn.pack() solarize_btn = button(filtersframe, text="solarize") solarize_btn.pack() black_and_white_btn = button(filtersframe, text="black , white") black_and_white_btn.pack() black_and_white_and_gray_btn = button(filtersframe, text="black , white , gray") black_and_white_and_gray_btn.pack() extreme_contrast_btn = button(filtersframe, text="extreme contrast") extreme_contrast_btn.pack() sepia_tint_btn = button(filtersframe, text="sepia tint") sepia_tint_btn.pack() adjust_component_btn = button(filtersframe, text="adjusts components") adjust_component_btn.pack() posterize_btn = button(filtersframe, text="posterize") posterize_btn.pack() simplify_btn = button(filtersframe, text="simplify") simplify_btn.pack() detect_edges_btn = button(filtersframe, text="detect edges") detect_edges_btn.pack() detect_edges_better_btn = button(filtersframe, text="detect edges better") detect_edges_better_btn.pack() blur_btn = button(filtersframe, text="blur") blur_btn.pack() flip_image = button(filtersframe, text="flip horizontal") flip_image.pack() #menu bar menubar = menu(mgui) filemenu = menu(menubar) #create menu options go under drop down filemenu.add_command(label="new") filemenu.add_command(label="open", command=open_img) filemenu.add_command(label="save as") filemenu.add_command(label="close", command=g_quit) #create main button (e.g file) contains drop down options menubar.add_cascade(label="file", menu=filemenu) mgui.config(menu=menubar) mgui.mainloop()
you've got 2 problems here. 1 of them, found yourself—you never call label2.pack()
, label never gets displayed. but, after fix that, label blank.
as label
documentation says:
you can use label display
photoimage
,bitmapimage
objects. when doing this, make sure keep reference image object, prevent being garbage collected python’s memory allocator.
you're not doing that. store photoimage
in local variable, tk_image
, goes away function exits.
that should explain why works if move code outside function. if that, tk_image
becomes global variable, doesn't go away until whole program exits. and, since you're using global variables on place implicitly, 1 possible fix use explicit global this:
def open_img(): global tk_image # rest of code
however, better trick cram image attribute of else that's going stick around, label
object itself:
def open_img(): # existing code label2.tk_image = imagetk.photoimage(pil_image_resized) label2.config(image=label2.tk_image, width=w_box, height=h_box)
now, image can't garbage collected until label that's using gets garbage collected (or until replace new image).
in fact, @ docs, example of using photoimage
label
does:
photo = photoimage(file="icon.gif") w = label(parent, image=photo) w.photo = photo w.pack()
Comments
Post a Comment