I am attempting to create a paint program but in my open() function, it raises this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\-------\PycharmProjects\Paint\main.py", line 31, in open
canvas.create_image(0, 0, anchor=NW, image=PIL.ImageTk.PhotoImage(file=Image.open("C:\\Users\\Anthony\\Pictures\\dddddd.png")))
File "C:\Users\-------\PycharmProjects\Paint\venv\lib\site-packages\PIL\ImageTk.py", line 103, in __init__
image = _get_image_from_kw(kw)
File "C:\Users\-------\PycharmProjects\Paint\venv\lib\site-packages\PIL\ImageTk.py", line 59, in _get_image_from_kw
return Image.open(source)
File "C:\Users\-------\PycharmProjects\Paint\venv\lib\site-packages\PIL\Image.py", line 3140, in open
prefix = fp.read(16)
File "C:\Users\-------\PycharmProjects\Paint\venv\lib\site-packages\PIL\Image.py", line 517, in __getattr__
raise AttributeError(name)
AttributeError: read
Exception ignored in: <function PhotoImage.__del__ at 0x000002177C9E93F0>
Traceback (most recent call last):
File "C:\Users\-------\PycharmProjects\Paint\venv\lib\site-packages\PIL\ImageTk.py", line 133, in __del__
name = self.__photo.name
AttributeError: 'PhotoImage' object has no attribute '_PhotoImage__photo'
Here is code relevant to the error:
def open():
path = filedialog.askopenfile(mode="r", filetypes=[("PNG Image", "*.png")], defaultextension="*.*")
width, height = Image.open(path.name, mode="r").size
canvas.config(width=width, height=height)
canvas.create_image(0, 0, anchor=NW, image=PIL.ImageTk.PhotoImage(file=Image.open(path.name)))
I replaced the "path.name" with a normal path thinking that it may be filedailog.askopenfile isn't providing a proper path although it didn't work. I did double slashes as well, just in case it was using something like "\n".
CodePudding user response:
file
option of ImageTk.PhotoImage()
should be a file name or file object, not instance of Image
.
Also you need to keep the reference of the image, otherwise it will be garbage collected after exiting the function.
It is better to use askopenfilename()
if you just want a filename. And you have called Image.open()
twice.
Below is the modified open()
:
def open():
# use askopenfilename() instead
path = filedialog.askopenfilename(filetypes=[("PNG Image", "*.png")],
defaultextension=".png")
if path:
image = Image.open(path)
width, height = image.size
tkimg = ImageTk.PhotoImage(image)
canvas.config(width=width, height=height)
canvas.create_image(0, 0, anchor=NW, image=tkimg)
canvas.image = tkimg # save the reference of image to avoid garbage collection
Note also that open()
is a built-in function of Python, it is better not to use it as your function name.