1
votes

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"

2
We don't need to see the code or errors in image form. But it'd be nice if you supplied the "bubble.png" image.PM 2Ring

2 Answers

1
votes

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)
0
votes

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