0

I'm having weird issues with some iterated buttons that are made inside of a function. I have my button list as a global variable and photos are saved within my main python folder.

When I use the Button image= attribute, the buttons aren't clickable and are kind of greyed out with no picture. When I use the Button text= attribute, the buttons are clickable and the text pops up, but the width and height attributes don't run. I haven't been able to find similar issues/answers here.

        from tkinter import *
        from tkinter import filedialog as fd
        from tkinter.messagebox import showinfo
        from PIL import Image, ImageTk

        def OnSomeClick():
        ---Some Code---
            if Orientation == 1:
                 for i in range(len(Ordered_xCoord)):
                 InitButtonPhoto = '{}.png'.format(i)
                 ButtonPhoto = PhotoImage(file=InitButtonPhoto)
                 ImageButtonList.append(Button(action_window, command=Command, bd=3, width=110,
                                          height=85, image=ButtonPhoto))
                 ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])
            #this top if statement is what runs with my test; the bottom is my original
            else:
                 for i in range(len(Ordered_xCoord)):
                 ImageButtonList.append(Button(action_window, 
                 image=PhotoImage(file='{}.png'.format(i)),
                                          command=Command, bd=3, width=85, height=110))
                 ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])

When loading the photo through PhotoImage(Image.open(file)), there is a traceback error. I'm not too sure why my photos are out of scope/garbaged or why the command working is dependent on the photo saving.

Traceback Error with Image.open:
Exception in Tkinter callback
Traceback (most recent call last):
  File "/Users/.conda/envs/CoordinateMath/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
    return self.func(*args)
  File "/Users/PycharmProjects/CoordinateMath/TkinterWindow.py", line 163, in Submit
    ButtonPhoto = PhotoImage(file=InitButtonPhoto)
  File "/Users/.conda/envs/CoordinateMath/lib/python3.8/tkinter/__init__.py", line 4064, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/Users/.conda/envs/CoordinateMath/lib/python3.8/tkinter/__init__.py", line 4009, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "<PIL.PngImagePlugin.PngImageFile image mode=RGB size=990x765 at 0x11034C310>": no such file or directory
Henry
  • 1
  • 2
  • 1
    Could you add the whole traceback error? – Random_Pythoneer59 Aug 23 '21 at 18:18
  • 1
    "no such file or directory" seems pretty self-explanatory. You've giving a path to a file that doesn't exist. – Bryan Oakley Aug 23 '21 at 18:23
  • @BryanOakley even with a direct path and real path, it shows a traceback error because it doesn't like PhotoImage(Image.open()) – Henry Aug 23 '21 at 18:30
  • That's a different problem. Your question is about the traceback with the "no such file" error, and the reason for the traceback is that you're giving an invalid filename. Another problem is likely related to this: https://stackoverflow.com/questions/16424091 – Bryan Oakley Aug 23 '21 at 18:42
  • The files are saving, so I would assume the filename is valid. With the link, you've posted. I've tried this, but it's not clear if I can do this in a for loop with a variable number of buttons. – Henry Aug 23 '21 at 18:50
  • can you please show how you import the modules (do this, update, then the other thing)? also provide a [mre] – Matiiss Aug 23 '21 at 19:05
  • btw it should be `ImageTk.PhotoImage(Image.open(file))` – Matiiss Aug 23 '21 at 19:56
  • @Matiiss That doesn't fix the problem. Still the same issue of the greyed out, unclickable buttons. – Henry Aug 23 '21 at 20:04
  • @Henry you also need to save a reference to the images not only to the buttons, append those images to a list too, you don't need indexes or anything, just append to some list the `ButtonPhoto` (using indexes tho would reduce the reference count) in the same loop you append the buttons – Matiiss Aug 23 '21 at 20:08
  • @Matiiss the images are indexed in a list outside of the code provided and I tried using this ImageTk.PhotoImage(List[i]), but the same issue occurs. When doing ImageTk.PhotoImage(Image.open(List[i])), there's a traceback error. – Henry Aug 23 '21 at 20:38
  • That traceback can't come from the code you posted. The error is telling you that `InitButtonPhoto` is an instance of a PIL image type, but in the code you posted it is clearly a string. – Bryan Oakley Aug 23 '21 at 20:43
  • @Henry keep it like this: `ButtonPhoto = ImageTk.PhotoImage(Image.open(InitButtonPhoto))` and then `some_list.append(ButtonPhoto)` – Matiiss Aug 23 '21 at 20:44

1 Answers1

0

Thank you, Matiiss and BryanOakley! The fix was a combo of the latest comment and putting my changing the formatting of my image list.

def onClick():
   global Image_List, Ordered_xCoord, Ordered_yCoord, ImagedButtonList
--some code---
   for i in range(len(Ordered_xCoord)):         
     y = myimage.save('{}.png'.format(i))
     z = ImageTk.PhotoImage(Image.open('{}.png'.format(i)))
     Image_List.append(z)
---more code----
   if PaperOrientation == 1:
        for i in range(len(Ordered_xCoord)):
            InitButtonPhoto = Image_List[i]
            ButtonPhoto = InitButtonPhoto
            ImageButtonList.append(Button(action_window, command=Command, bd=3, width=110,
                              height=85, image=ButtonPhoto))
            ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])
    else:
        for i in range(len(Ordered_xCoord)):
            InitButtonPhoto = Image_List[i]
            ButtonPhoto = InitButtonPhoto
            ImageButtonList.append(Button(action_window, command=Command, bd=3, width=85,
                              height=110, image=ButtonPhoto))
            ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])

Kind of sloppy on my part, but it works.

Henry
  • 1
  • 2