Цикл верхнего уровня Tkinter

У меня есть этот скрипт, в котором я хочу выбрать изображение из каталога с помощью Tkinter, а затем выбрать на нем пиксель, но похоже, что tkinter.mainloop() никогда не заканчивается. Пожалуйста помоги

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)

person Ronny Strom    schedule 13.12.2017    source источник
comment
это нормально во всех графических интерфейсах - mainloop должен работать, пока вы не закроете окно. Он получает события из системы, отправляет события в виджеты, меняет виджеты, перерисовывает все — и все это в цикле. И с этим нужно научиться жить ;)   -  person furas    schedule 13.12.2017
comment
вы должны распечатать его внутри callback или закрыть окно.   -  person furas    schedule 13.12.2017
comment
Я знаю, но проблема в том, что после того, как я закрыл окно, оно все еще находится в этом цикле, потому что последняя строка не печатается. Я думаю, что немного напутал с tkinter.Tk() и tkinter.Toplevel(), поэтому он не работает должным образом.   -  person Ronny Strom    schedule 13.12.2017
comment
теперь я вижу, что вы правы - вы закрываете только Toplevel окно, но Tk() все еще работает - вы должны присвоить Tk() переменной - т.е. root чтобы вы могли сделать root.destroy() . Вы можете добавить кнопку с command=other_callback, чтобы назначить функцию, которая будет выполнять window.destroy() и root.destroy()   -  person furas    schedule 13.12.2017
comment
или вместо создания окна Toplevel используйте root.deiconify(), чтобы отобразить Tk() и поместить все в это окно   -  person furas    schedule 13.12.2017
comment
или используйте Label, чтобы отобразить его внутри окна.   -  person furas    schedule 13.12.2017


Ответы (1)


Используйте deiconify(), чтобы отобразить Tk() окно и использовать его вместо Toplevel()

Кстати: обратный вызов не должен возвращать значение, потому что никто не может получить это значение.

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)

Кстати: вы можете использовать Label для его отображения

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)

введите здесь описание изображения

person furas    schedule 13.12.2017
comment
В некоторых средах может потребоваться вызов root.deiconify() сразу после root.iconify(), чтобы снова сделать root видимым. - person Nae; 13.12.2017