Search code examples
pythonimagetkinterpython-3.5toplevel

Tkinter toplevel loop


I have this script where I want to choose image from directory using Tkinter and then choose pixel on it but looks like tkinter.mainloop() never ends. Please help

import tkinter.filedialog
from PIL import Image, ImageTk


def callback(event):
    print("Starting pixel of object is: ", event.x, event.y)
    global ps
    ps[0] = event.x
    ps[1] = event.y
    return event.x, event.y


tkinter.Tk().withdraw()
image = tkinter.filedialog.askopenfilename()
ps = [0, 0]
window = tkinter.Toplevel()
img = Image.open(image)
canvas = tkinter.Canvas(window, width=img.size[0], height=img.size[1])
canvas.pack()
image_tk = ImageTk.PhotoImage(img)
canvas.create_image(img.size[0] // 2, img.size[1] // 2, image=image_tk)
canvas.bind("<Button-1>", callback)
tkinter.mainloop()
print(ps)

Solution

  • Use deiconify() to show back Tk() window and use it instead of Toplevel()

    BTW: callback doesn't have to return value because there is nobody to receive this value.

    import tkinter.filedialog
    from PIL import Image, ImageTk
    
    # --- functions ---
    
    def callback(event):
        global ps # at the beginning to make it more readable
    
        print("Starting pixel of object is: ", event.x, event.y)
        ps[0] = event.x
        ps[1] = event.y
    
    # --- main ---
    
    ps = [0, 0]
    
    root = tkinter.Tk()
    root.withdraw()
    
    image = tkinter.filedialog.askopenfilename()
    
    img = Image.open(image)
    image_tk = ImageTk.PhotoImage(img)
    
    root.deiconify() # <-- show `root` again
    
    canvas = tkinter.Canvas(root, width=img.size[0], height=img.size[1])
    canvas.pack()
    canvas.create_image(img.size[0] // 2, img.size[1] // 2, image=image_tk)
    canvas.bind("<Button-1>", callback)
    
    tkinter.mainloop()
    
    print(ps)
    

    BTW: you can use Label to display it

    import tkinter
    import tkinter.filedialog
    from PIL import Image, ImageTk
    
    def callback(event):
        global ps
    
        print("Starting pixel of object is: ", event.x, event.y)
        ps[0] = event.x
        ps[1] = event.y
    
        label['text'] = str(ps)
    
    # --- main ---
    
    ps = [0, 0]
    
    root = tkinter.Tk()
    root.withdraw()
    
    image = tkinter.filedialog.askopenfilename()
    
    img = Image.open(image)
    image_tk = ImageTk.PhotoImage(img)
    
    root.deiconify()
    
    canvas = tkinter.Canvas(root, width=img.size[0], height=img.size[1])
    canvas.pack()
    canvas.create_image(img.size[0] // 2, img.size[1] // 2, image=image_tk)
    canvas.bind("<Button-1>", callback)
    
    label = tkinter.Label(root)
    label.pack()
    
    tkinter.mainloop()
    
    print(ps)
    

    enter image description here