Python: Tkinter TclError: can't invoke “image” command

只愿长相守 提交于 2021-02-10 16:47:49

问题


preface: I have currently tried most things and there are few qusestions asked on stackoverflow on this question and i cant seem to wrap my head around it so im going to need some help

application: the purpose of this program is to animate an oval and a picture, the oval works fine, but the picture is struggling, you could remove the image or alien2 and the program should run fine.

CODE

image form

from tkinter import *
import time
from PIL import Image,ImageFilter
from PIL import ImageTk

class alien(object):
     def __init__(self):


        self.root = Tk()
        self.canvas = Canvas(self.root, width=400, height = 400)
        self.canvas.pack()
        self.cardPath = Image.open('bubble.png')
        self.resCard = cardPath.resize((100,100))
        self.CardVar = ImageTk.PhotoImage(resCard,master=root)
        self.alien1 = self.canvas.create_oval(20, 260, 120, 360, outline='white',fill='blue')
        self.alien2 = self.canvas.create_image(100,100,CardVar,anchor=CENTER)
        self.canvas.pack()
        self.root.after(0, self.animation)
        self.root.mainloop()


     def animation(self):
        track = 0
        while True:
            x = 5
            y = 0
            if track == 0:
               for i in range(0,51):
                    time.sleep(0.025)
                    self.canvas.move(self.alien1, x, y)
                    self.canvas.move(self.alien2, x, y)
                    self.canvas.update()
               track = 1
               print("check")

            else:
               for i in range(0,51):
                    time.sleep(0.025)
                    self.canvas.move(self.alien1, -x, y)
                    self.canvas.move(self.alien2, -x, y)
                    self.canvas.update()
               track = 0
            print(track)

alien()

ERROR:

image

runfile('/Users/Stian/.spyder-py3/animation_test.py', wdir='/Users/Stian/.spyder-py3') Traceback (most recent call last):

File "", line 1, in runfile('/Users/Stian/.spyder-py3/animation_test.py', wdir='/Users/Stian/.spyder-py3')

File "/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 705, in runfile execfile(filename, namespace)

File "/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace)

File "/Users/Stian/.spyder-py3/animation_test.py", line 57, in alien()

File "/Users/Stian/.spyder-py3/animation_test.py", line 25, in init self.CardVar = ImageTk.PhotoImage(resCard,master=root)

File "/anaconda3/lib/python3.6/site-packages/PIL/ImageTk.py", line 124, in init self.__photo = tkinter.PhotoImage(**kw)

File "/anaconda3/lib/python3.6/tkinter/init.py", line 3542, in init Image.init(self, 'photo', name, cnf, master, **kw)

File "/anaconda3/lib/python3.6/tkinter/init.py", line 3498, in init self.tk.call(('image', 'create', imgtype, name,) + options)

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


I know the code is not beautiful, but it's a test environment and as mentioned everything should work flawless, but it breaks when an image is used instead of an oval which should not make a big difference. Thanks in advance!


PROBLEM SOLVED

turns out the problem turned up when assigning master inside PhotoImage(), when i removed that the application did not get the TclError

NEW PROBLEM

the changes i made to the code were from this:

        self.cardPath = Image.open('bubble.png')
        self.resCard = cardPath.resize((100,100))
        self.CardVar = ImageTk.PhotoImage(resCard,master=root)

to this:

    self.cardPath = Image.open('bubble.png')
    self.resCard = cardPath.resize((100,100))
    self.CardVar = ImageTk.PhotoImage(resCard)

THE NEW ERROR

image form


File "", line 1, in runfile('/Users/Stian/.spyder-py3/animation_test.py', wdir='/Users/Stian/.spyder-py3')

File "/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 705, in runfile execfile(filename, namespace)

File "/anaconda3/lib/python3.6/site-packages/spyder/utils/site/sitecustomize.py", line 102, in execfile exec(compile(f.read(), filename, 'exec'), namespace)

File "/Users/Stian/.spyder-py3/animation_test.py", line 56, in alien()

File "/Users/Stian/.spyder-py3/animation_test.py", line 27, in init self.alien2 = self.canvas.create_image(100,100,CardVar,anchor=CENTER)

File "/anaconda3/lib/python3.6/tkinter/init.py", line 2486, in create_image return self._create('image', args, kw)

File "/anaconda3/lib/python3.6/tkinter/init.py", line 2477, in _create *(args + self._options(cnf, kw))))

TclError: unknown option "pyimage21"


回答1:


You have a few places in your code where you forgot self. But the cause of your main error is that you need to pass the image name as a keyword arg. Here's a repaired version of your code.

from tkinter import *
import time
from PIL import Image,ImageFilter
from PIL import ImageTk

class alien(object):
     def __init__(self):
        self.root = Tk()
        self.canvas = Canvas(self.root, width=400, height=400)
        self.canvas.pack()
        self.cardPath = Image.open('bubble.png')
        self.resCard = self.cardPath.resize((100, 100))
        self.CardVar = ImageTk.PhotoImage(self.resCard)
        self.alien1 = self.canvas.create_oval(20, 260, 120, 360, outline='white', fill='blue')
        self.alien2 = self.canvas.create_image(100, 100, image=self.CardVar, anchor=CENTER)
        self.canvas.pack()
        self.root.after(0, self.animation)
        self.root.mainloop()

     def animation(self):
        track = 0
        while True:
            x = 5
            y = 0
            if track == 0:
               for i in range(51):
                    time.sleep(0.025)
                    self.canvas.move(self.alien1, x, y)
                    self.canvas.move(self.alien2, x, y)
                    self.canvas.update()
               track = 1
               print("check")
            else:
               for i in range(51):
                    time.sleep(0.025)
                    self.canvas.move(self.alien1, -x, y)
                    self.canvas.move(self.alien2, -x, y)
                    self.canvas.update()
               track = 0
            print(track)

alien()

BTW, it's not a good idea to use time.sleep in GUI programs. It puts everything to sleep, so the GUI cannot update itself, or respond to any user input. It would be better to reorganize your code so that animation uses the .after method.

Here's a version of the animation method that doesn't use sleep. You need to add self.count = 0 to the __init__ method.

 def animation(self):
    y = 0
    x = 5 if self.count < 50 else -5
    self.count = (self.count + 1) % 100
    self.canvas.move(self.alien1, x, y)
    self.canvas.move(self.alien2, x, y)
    self.root.after(25, self.animation)



回答2:


After a while i edited the code and made it work. here is the full code

from tkinter import *
import time
import PIL
from PIL import Image,ImageFilter
from PIL import ImageTk

class alien(object):
    def __init__(self):

    self.root = Tk()
    self.canvas = Canvas(self.root, width=400, height = 400)
    self.canvas.pack()

    CardVar = ImageTk.PhotoImage(file='bubble.png')
    self.alien1 = self.canvas.create_oval(20, 260, 120, 360, outline='white',fill='blue')
    self.alien2 = self.canvas.create_image((100,100),image=CardVar,anchor=CENTER)
    self.canvas.pack()
    self.root.after(0, self.animation)
    self.root.mainloop()


 def animation(self):
    track = 0
    while True:
        x = 5
        y = 0
        if track == 0:
           for i in range(0,51):
                time.sleep(0.025)
                self.canvas.move(self.alien1, x, y)
                self.canvas.move(self.alien2, x, y)
                self.canvas.update()
           track = 1
           print("check")

        else:
           for i in range(0,51):
                time.sleep(0.025)
                self.canvas.move(self.alien1, -x, y)
                self.canvas.move(self.alien2, -x, y)
                self.canvas.update()
           track = 0
        print(track)
alien()

The problem

the cardVar was never able to find the correct image even though it was in the same folder, so i tried to do cardVar.show() and another image that was located far away showed up so it seems like something was saved in my memory. so i decided to restart kernel and everything went smooth



来源:https://stackoverflow.com/questions/51986128/python-tkinter-tclerror-cant-invoke-image-command

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!