Python代码问题,应用程序已被破坏Tcl错误

发布于 2024-11-10 02:23:53 字数 1445 浏览 4 评论 0原文

我正在制作一个 Tkinter GUI,除了调用图像之外什么都不做 - 当然,我一直在努力寻找像样的 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:无法调用“image”命令:应用程序已被破坏

,我不知道出了什么问题。我无法移动图像命令,并且以某种方式我需要“保存”它,这样它就不会被破坏。我知道这里还有其他代码错误,但我认为如果我弄清楚了我得到的 TclError,我就可以把其他一切都搞清楚。

如果有更简单的方法来完成这一切,请告诉我们!

I am making a Tkinter GUI to do nothing except call images - and of course, I have struggled to find decent tkinter documentation all along.

There is a line of my code which cannot seem to do as asked - I want to call up all the values in a dictionary and individually print and pull an image by the same name for each one before the next value is called up. I have tried dict.itervalues() and dict.values() and can't seem to figure anything out altogether...

Anyway, here is the snippet:

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()

Finally, at the end, it pulls up one or two images and then I get the following error:

TclError: can't invoke "image" command: application has been destroyed

and I can't figure out what is wrong. I can't move the image command, and somehow I need to "save" it so it isn't destroyed. I know there are other code errors here, but I think that if I figure out the TclError that I am getting that I can set everything else straight.

If there is an easier way to do all this please do tell!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

怀里藏娇 2024-11-17 02:23:54

这是一种可能性,尽管它的结构与您的示例不同。它将四个 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

Here is one possibility, although it is structured differently than your example. It stacks the four 100 pixel square images on top of one another. I believe you need to keep a separate reference to each Image object, so I tucked them away in the images dictionary.

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()

Here is a good link discussing the PhotoImage class.

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

浅暮の光 2024-11-17 02:23:54

看来您没有理解事件驱动编程的想法。您应该创建整个 GUI 一次,用小部件填充它,设置事件,然后进入无限循环。 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()

It seems that you did not get the idea of Event-driven programming. You should create whole GUI once, fill it with widgets, setup the events and then enter infinite loop. The GUI should call callback functions based on your event to function binding. So those parts of your program should definitely be called just once: root = tk.Tk(), root.mainloop().

Edit: Added Event-driven programming "idea example".

from Tkinter import *

master = Tk()

def callback():
    print "click!"

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

mainloop()
情绪操控生活 2024-11-17 02:23:53

我已经四处寻找一个好的解决方案,但尚未找到正确的解决方案。查看 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

这意味着如果您想要进行 BRUTAL hack,您可以按照 jtp 链接中所述设置 PhotoImage 。

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

然后,您可以在程序退出之前执行以下操作:

photo.name = None

这将阻止它尝试在 PhotoImage 删除中清理自身,并阻止在 del 方法中调用异常。我真的不建议你这样做,除非你已无路可走,而且别无选择。

我将继续研究这个问题,如果我找到更好的解决方案,我将用更好的解决方案编辑这篇文章(希望在此之前有人能给出正确的解决方案)。

I have looked around for a good solution to this but have yet to find the proper solution. Looking at the Tkinter.py class it looks like the Image del value is:

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

This means if you wanted to do a BRUTAL hack you could setup a PhotoImage as described in jtp's link.

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

Then you could just before the program exited do the following hack:

photo.name = None

This would prevent it from trying to clean itself up in the PhotoImage delete and prevent the exception from being called in the del method. I do not really recommend you do this unless your back is up against the wall, and you have no alternative.

I will continue to look into this and if I find a better solution will edit this post with a better one (hopefully someone will give the correct solution before then).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文