#python #tkinter
#питон #изображение #tkinter #tkinter-canvas
Вопрос:
Этот код работает:
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 gui, в котором он отображается.
2. @maszoka:
effbot.org
может быть отключено, но вы все равно можете прочитать ссылку Почему мои изображения Tkinter не отображаются? благодаря машине обратного доступа Internet Archive.3. Также обратите внимание, что та же проблема может возникнуть везде, где используются временные
PhotoImage
s, например, в вызывающей последовательности, такой какlabel = Label(image=ImageTk.PhotoImage(Image.fromarray(data)))
.
Ответ №1:
Переменная photo
— это локальная переменная, которая собирает мусор после создания экземпляра класса. Сохраните ссылку на фотографию, например:
self.photo = tkinter.PhotoImage(...)
Если вы выполните поиск в Google по запросу «изображение tkinter не отображается», первый результат будет таким:
Почему мои изображения Tkinter не отображаются?(Ответ на часто задаваемые вопросы в настоящее время не устарел)
Комментарии:
1. Вау. Считают ли они это ошибкой в tkinter? Они должны.
2. Я нашел очень старый билет, уже закрытый без исправления: bugs.python.org/issue632323
3. Ссылка не работает atm, есть ли другой способ, кроме использования «global»?
4. @aru: В этом примере показано, как это сделать без использования глобального.
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()
Просто добавьте global в определение img, и оно будет работать
Комментарии:
1. Этот ответ подходит для программы, которая просто использует функции, но если, как в случае с OP, вы используете класс,
global
это не тот путь.
Ответ №3:
Проблема в том, что Python автоматически удаляет ссылки на переменную с помощью процесса, известного как сборка мусора. Решение состоит в том, чтобы сохранить ссылку или создать новую ссылку.
Ниже приведены способы:
- Используется
self
для увеличения количества ссылок и сохранения ссылки.
import tkinter
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
self.photo = tkinter.PhotoImage(file = './test.gif') # Changes here
canvas.create_image(0, 0, image=self.photo) # Changes here
root = tkinter.Tk()
test = Test(root)
root.mainloop()
- Сохранение его в список для увеличения количества ссылок и сохранения ссылки.
import tkinter
l=[]
class Test:
def __init__(self, master):
canvas = tkinter.Canvas(master)
canvas.grid(row = 0, column = 0)
photo = tkinter.PhotoImage(file = './test.gif')
l.append(photo)
canvas.create_image(0, 0, image=photo)
root = tkinter.Tk()
test = Test(root)
root.mainloop()
При использовании метода 2 вы можете либо создать глобальный список, как я, либо использовать list внутри класса. И то, и другое сработало бы.
Некоторые полезные ссылки:
Ответ №4:
Просто добавьте global photo
в качестве первой строки внутри функции.
Комментарии:
1. А затем вы создаете 2-й
Test
экземпляр, и первый экземпляр теряет свое изображение. Поздравляю.2. Определенно нет необходимости использовать
global
его в классе.self.
позаботится обо всем этом.