tkinter canvas обновляется только с ошибкой

Я пишу код, который будет отображать .png в виджете холста всякий раз, когда пользователь выбирает элемент в виджете Treeview. Когда я запускаю свой код, изображение отображается на холсте только тогда, когда в функции selectedItems возникает ошибка. Пока что это может быть любая ошибка, но изображение не будет отображаться, если не возникнет ошибка. Я пытался вставить временную задержку и использовал инструмент отладки, но до сих пор не понимаю, почему это происходит. Если ошибки нет, Treeview по-прежнему создает индекс для выбранного элемента, но холст не обновляется изображением. Может ли кто-нибудь просветить меня?

import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk

def selectedItems(event):
    item = tree.selection()
    item_iid = tree.selection()[0]
    parent_iid= tree.parent(item_iid)
    directory= r"..."
    if tree.item(parent_iid, "text") != "":
        imageFile= directory + tree.item(item_iid, "text")
        image_o= Image.open(imageFile)
        image_o.thumbnail([683, 384], Image.ANTIALIAS)
        image1= ImageTk.PhotoImage(image_o)
        canvas1.create_image((0, 0), anchor= "nw", image= image1)
        a= 'hello' + 7

tree.bind("<<TreeviewSelect>>", selectedItems)

Это ошибка, которую я получаю:

Traceback (most recent call last):
  File "C:\Program Files\Python36\lib\tkinter\__init__.py", line 1699, in __call__
    return self.func(*args)
  File ".\front_end_DataManager.py", line 21, in selectedItems
    a= 'hello' + 7
TypeError: must be str, not int

Я знаю о TypeError. Это сделано намеренно, чтобы изображение отображалось. Я думаю, что проблема в функции tkinter call. Любые идеи?


person Drew Wilkins    schedule 26.12.2017    source источник
comment
всегда помещайте полное сообщение об ошибке (Traceback) в вопрос (в виде текста, а не скриншота). Есть и другая полезная информация.   -  person furas    schedule 27.12.2017
comment
Как минимум по крайней мере нам нужно воспроизвести вашу ошибку с загруженным кодом. Я предполагаю, что в конечном итоге мы дойдем до того, что вам нужно будет использовать глобальную ссылку на ваше изображение.   -  person Nae    schedule 27.12.2017
comment
Спасибо за рекомендации по этикету публикации вопросов. Я обновил свой вопрос, чтобы быть более кратким и включить сообщения об ошибках.   -  person Drew Wilkins    schedule 27.12.2017
comment
вы не можете добавить строку "hello" и число 7 - вам нужно преобразовать число в строку str(7), чтобы объединить оба "hello" + str(7)   -  person furas    schedule 27.12.2017
comment
@furas Я знаю, что строки так не работают. Это была строка, которую я вставил намеренно, чтобы изображение отображалось правильно. Я думаю, что Наэ что-то задумал.   -  person Drew Wilkins    schedule 27.12.2017
comment
Теперь вашему коду не хватает полноты. Есть ссылка tree, но она никогда не была объявлена, а также вы должны были сохранить ссылку tkinter.Tk и добавить mainloop.   -  person Nae    schedule 27.12.2017
comment
Возможный дубликат Не удается отобразить изображение в Tkinter   -  person Nae    schedule 27.12.2017


Ответы (1)


У вас проблема с ошибкой в ​​tkinter, которая удаляет из памяти изображение, назначенное локальной переменной в функции, а затем не отображает его. Вы должны назначить его глобальной переменной или классу.

См. global в коде - таким образом image1 будет глобальной переменной, а не локальной.

def selectedItems(event):
    global image1

    item = tree.selection()
    item_iid = tree.selection()[0]
    parent_iid = tree.parent(item_iid)
    directory = r"..."
    if tree.item(parent_iid, "text") != "":
        imageFile = directory + tree.item(item_iid, "text")
        image_o = Image.open(imageFile)
        image_o.thumbnail([683, 384], Image.ANTIALIAS)
        image1 = ImageTk.PhotoImage(image_o)
        canvas1.create_image((0, 0), anchor= "nw", image= image1)

См. также «Примечание:» в конце страницы Класс Tkinter PhotoImage.

person furas    schedule 26.12.2017
comment
Ага. Это полностью решило это. Я просмотрел класс Tkinter PhotoImage, на который вы ссылались ранее, и сохранил изображение в переменной, которая будет возвращена в функции. Это не сработало, но глобальное решение полностью решает эту проблему. Спасибо. - person Drew Wilkins; 27.12.2017
comment
функции, назначенные bind()/command=/after(), выполняются mainloop() позже, но mainloop() не присваивает возвращаемые значения глобальным переменным. Он не заботится о возвращаемых значениях. Это хранит их. - person furas; 27.12.2017