Как добавить изображения в Tkinter Treeview в качестве значений?

Как я могу добавить изображение в ttk Treeview? Пример кода:

from tkinter import *
from ttk import *
from tkinter import ttk
import json
from PIL import Image, ImageTk
okno = Tk()

def maketable():
    style = ttk.Style(okno)
    style.configure("TVS.Treeview", rowheight=40)
    tv = Treeview(okno, style="TVS.Treeview")

    tv['columns'] = ('LName', 'Pic')
    tv.heading("#0", text='Jméno', anchor='w')
    tv.column("#0", anchor="w", width=200)

    tv.heading('LName', text='Příjmení')
    tv.column('LName', anchor='center', width=200)

    tv.heading('Pic', text='Obrazek')
    tv.column('Pic', anchor='center', width=200)

    dbf = open("xxx.json", 'r')
    db = json.loads(dbf.read())
for i in range(0, len(db)):
    root_pic1 = Image.open(db[i]["Pic"])
    root_pic2 = ImageTk.PhotoImage(root_pic1) 
    tv.insert('', 'end', image=root_pic2, text=db[i]['Name'], values=(db[i]['LName'])) 


tv.pack()


def main():
    okno.mainloop()

if __name__ == '__main__':
    maketable()
    main()

Я хочу, чтобы в столбце «Изображение» были изображения — это означает, что изображение не должно быть в #0, потому что это значение. В db[i]["Pic"] есть путь к файлу. В values=() не могу добавлять изображения — ничего не показывает.

РЕДАКТИРОВАТЬ: спасибо за решение, но не работает с несколькими изображениями:

for i in range(0, len(db)):
    tv._image = Image
    tv._image = Image.open(db[i]["Pic"])
    tv._image.thumbnail((100, 200), PIL.Image.ANTIALIAS)
    tv._image = ImageTk.PhotoImage(tv._image)
    tv.insert('', 'end', image=tv._image, values=(db[i]['Name'], db[i]['LName'])) 


tv.pack()

person Makalone LOgman    schedule 18.11.2017    source источник
comment
Это может помочь.   -  person Nae    schedule 18.11.2017
comment
Я не вижу никакого кода, который загружает изображение. Покажи это. Если вы используете PIL/Pillow, прочитайте примечание о проблеме с Pillow и сборщиком мусора на странице effbot.org/tkinterbook/ фотоизображение.htm   -  person furas    schedule 18.11.2017
comment
@Nae пытался, ничего не получилось   -  person Makalone LOgman    schedule 18.11.2017
comment
@furas отредактировал код с предложением Nae.   -  person Makalone LOgman    schedule 18.11.2017
comment
Вам нужно сохранить ссылку на PhotoImage, иначе он не будет отображаться.   -  person Stevo Mitric    schedule 18.11.2017
comment
@StevoMitricчто? Как я могу это сделать... Извините, я новичок   -  person Makalone LOgman    schedule 18.11.2017
comment
@MakaloneLOgman кажется, вы не читали о проблеме со сборщиком мусора - ссылка, добавленная Nae, показывает ту же проблему - изображение, назначенное локальной переменной, удаляется из памяти, и Tkitner не может его отобразить.   -  person furas    schedule 18.11.2017
comment
в начале вы можете использовать global root_pic2 в maketable, и изображение будет назначено глобальной переменной, и Python не удалит его из памяти.   -  person furas    schedule 18.11.2017


Ответы (1)


Как отметили @Nae и @furas, локальные переменные удаляются, когда функция завершается, а ваши изображения удаляются сборщиком мусора.

вам нужно будет сделать что-то вроде:

tv._image = Image.open('test.png')
tv._image = ImageTk.PhotoImage(tv._image)

for i in range(0, len(db)):

    tv.insert('', 'end', image=tv._image, text=db[i]['Name'], values=(db[i]['LName']))

или определить их вне функции. Было бы идеально, если бы вы использовали классы и могли вызывать self.root_pic = ...

РЕДАКТИРОВАТЬ: Что касается большего количества изображений, вам нужно будет создать список:

tv._images = []    

for i in range(0, len(db)):
    image = Image.open(db[i]["Pic"])
    image = ImageTk.PhotoImage(image)
    image.thumbnail((100, 200), PIL.Image.ANTIALIAS) # resize
    tv._images.append(image)

    tv.insert('', 'end', image=tv._images[-1], text=db[i]['Name'], values=(db[i]['LName']))
person Stevo Mitric    schedule 18.11.2017
comment
РЕДАКТИРОВАТЬ: не работает с большим количеством записей; _ для i в диапазоне (0, len(db)): tv._image = Image tv._image = Image.open(db[i][Pic]) tv._image.thumbnail((100, 200), PIL.Image .ANTIALIAS) tv._image = ImageTk.PhotoImage(tv._image) tv.insert('', 'end', image=tv._image, values=(db[i]['Name'], db[i][ 'LName'])) tv.pack()_ - person Makalone LOgman; 18.11.2017
comment
Обновлен ответ для большего количества изображений. - person Stevo Mitric; 18.11.2017
comment
Вопрос был об использовании Image как значения, а не как части первого столбца #0. - person buhtz; 14.02.2018