Проблема с кодом Python, приложение было уничтожено Ошибка Tcl

Я создаю графический интерфейс Tkinter, который ничего не делает, кроме изображений вызовов - и, конечно, я изо всех сил пытался найти приличную документацию по tkinter.

В моем коде есть строка, которая, кажется, не может работать так, как требуется - я хочу вызвать все значения в словаре и по отдельности распечатать и вытянуть изображение под тем же именем для каждого из них, прежде чем будет вызвано следующее значение. Я пробовал dict.itervalues ​​() и dict.values ​​() и не могу ничего понять вообще...

Во всяком случае, вот фрагмент:

for key in ansDict.iterkeys(): #using the iterkeys function... kind of
    x=key

    root = tk.Tk() # root window created (is this in the right place?)
    root.title('C H E M I S T R Y   A B C\'s')

    frameAns=tk.Frame(root)
    frameAns.grid(row=0, column=0, sticky=tk.NW)

    for i in range(len(ansDict[x])):
        print '-->' + ansDict[x][i]

    for value in ansDict.itervalues(): #This is the most important part

        for i in range(len(value)): #pulls value list from dictionary named ansDict
            picRef1 = Image.open(value[i] + '.jpg') #calls image file by the same name using PIL
            photo1 = ImageTk.PhotoImage(picRef1, master=root)

            button1 = tk.Button(frameAns, compound=tk.TOP, image=photo1, text=str(value[i]) + '\nClose me!', bg='white') #pulls up button onto which the image is pasted
            button1.grid(sticky=tk.NW, padx=2, pady=2) #places button on grid
            button1.image=photo1

            root.mainloop()

Наконец, в конце он вытягивает одно или два изображения, а затем я получаю следующую ошибку:

TclError: невозможно вызвать команду "изображение": приложение было уничтожено

и я не могу понять, что не так. Я не могу переместить команду изображения, и каким-то образом мне нужно "сохранить" ее, чтобы она не была уничтожена. Я знаю, что здесь есть и другие ошибки в коде, но я думаю, что, если я выясню, что получаю TclError, я могу исправить все остальное.

Если есть более простой способ сделать это, пожалуйста, сообщите!

3 ответа

Я искал хорошее решение для этого, но пока не нашел правильного решения. Глядя на класс Tkinter.py, выглядит, что значение Image del:

def __del__(self):
    if self.name:
        try:
            self.tk.call('image', 'delete', self.name)
        except TclError:
            # May happen if the root was destroyed
            pass

Это означает, что если вы хотите сделать ЗЛОКАЧЕЕ взлом, вы можете установить PhotoImage, как описано в ссылке jtp.

photo = tk.PhotoImage(file="C:/myimage.gif")
widget["image"] = photo
widget.image = photo

Тогда вы могли бы незадолго до выхода из программы сделать следующий хак:

photo.name = None

Это не позволит ему попытаться очистить себя при удалении PhotoImage и не вызовет исключение в методе del. Я действительно не рекомендую вам делать это, если вы не прислонились спиной к стене, и у вас нет альтернативы.

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

Похоже, вы не поняли, что такое программирование на основе событий. Вы должны создать целый графический интерфейс один раз, заполнить его виджетами, настроить события и затем войти в бесконечный цикл. GUI должен вызывать функции обратного вызова, основанные на привязке вашего события к функции. Таким образом, эти части вашей программы должны определенно вызываться только один раз: root = tk.Tk(), root.mainloop(),

Редактировать: добавлено программирование на основе событий "пример идеи".

from Tkinter import *

master = Tk()

def callback():
    print "click!"

b = Button(master, text="OK", command=callback)
b.pack()

mainloop()

Вот одна из возможностей, хотя она структурирована иначе, чем ваш пример. Он накладывает четыре квадрата размером 100 пикселей друг на друга. Я считаю, что вам нужно хранить отдельную ссылку на каждый объект Image, поэтому я спрятал их в словаре изображений.

from Tkinter import *
import os
from PIL import Image, ImageTk

image_names = { '1':'one','2':'two','3':'three','4':'four' }
images = {}

root = Tk()
root.title("HELLO")
frm = Frame(root)

for v in image_names.itervalues():
   images[v] = {}
   images[v]['i']  = Image.open("%s%s.jpg" % (os.path.dirname(__file__), v))
   images[v]['pi'] = ImageTk.PhotoImage(images[v]['i'])
   images[v]['b']  = Button(frm, image=images[v]['pi'])
   images[v]['b'].pack()

frm.pack()

mainloop()

Вот хорошая ссылка, обсуждающая класс PhotoImage.

http://effbot.org/tkinterbook/photoimage.htm

Другие вопросы по тегам