Почему изображение Tkinter не отображается, если оно создано в функции?

#python #tkinter #popup #photoimage

Вопрос:

Этот код работает:

 import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
canvas.create_image(0, 0, image=photo)
root.mainloop()
 

Он показывает мне изображение.

Теперь этот код компилируется, но он не показывает мне изображение, и я не знаю почему, потому что это один и тот же код в классе:

 import tkinter

class Test:
    def __init__(self, master):
        canvas = tkinter.Canvas(master)
        canvas.grid(row = 0, column = 0)
        photo = tkinter.PhotoImage(file = './test.gif')
        canvas.create_image(0, 0, image=photo)

root = tkinter.Tk()
test = Test(root)
root.mainloop()
 

Комментарии:

1. effbot.org находится внизу. Суть этого в том, что изображение передается по ссылке. Если ссылка относится к локальной переменной, указанная память используется повторно, и ссылка устаревает. Переменная, хранящая изображение, должна находиться в той же области (должна иметь тот же срок службы), что и объект графического интерфейса Tk, на котором он отображается.

2. @maszoka: effbot.org возможно, не работает, но вы все еще можете прочитать ссылку, почему мои изображения Tkinter не отображаются? благодаря интернет-архиву wayback machine .

Ответ №1:

Переменная photo -это локальная переменная, которая собирает мусор после создания экземпляра класса. Сохраните ссылку на фотографию, например:

 self.photo = tkinter.PhotoImage(...)
 

Если вы выполните поиск в Google по запросу «изображение tkinter не отображается», первый результат будет таким:

Почему мои изображения Tkinter не отображаются? (Ответ на часто задаваемые вопросы в настоящее время не устарел)

Комментарии:

1. лмао, отличный ответ !

2. Вау. Считают ли они это ошибкой в tkinter? Они должны.

3. Я нашел очень старый билет, уже закрытый без исправления: bugs.python.org/issue632323

4. Ссылка не работает, есть ли другой способ, чем использовать «глобальный»?

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

Ответ №2:

 from tkinter import *
from PIL import ImageTk, Image

root = Tk()

def open_img():
    global img
    path = r"C:.....\"
    img = ImageTk.PhotoImage(Image.open(path))
    panel = Label(root, image=img)
    panel.pack(side="bottom", fill="both")
but1 = Button(root, text="click to get the image", command=open_img)
but1.pack()
root.mainloop() 
 

Просто добавьте глобальный в определение img, и это сработает

Комментарии:

1. Этот ответ подходит для программы, которая просто использует функции, но если, как в случае с операцией, вы используете класс, то global это не тот путь.

Ответ №3:

Просто добавьте global photo в качестве первой строки внутри функции.

Комментарии:

1. А затем вы создаете 2-й Test экземпляр, и первый экземпляр теряет свой образ. Поздравления.

2. Там определенно нет никакой необходимости использовать global , когда в классе. self. заботится обо всем этом.