-1

Currently I loop through a list of image names and make them into a tkinter PhotoImage. These are saved as variables under their respective names from the list using vars()[var]. In this case vars()[var] represents the value of the item in a list making it into a variable name for the images.

example shown below:

list = ["a","b","c","d"] #and so on...
image_id = []

for x in range((len)list):
    var = list[x]
    vars()[var] = tk.PhotoImage(file = var + ".gif")
    image_id.append(vars()[var])  #this adds the identity of all photoimages to a list for later use

According to my tests I can use the images via the variable names or identities as long as it is within the same function. This is due to the variables being local. The problem is that even though the image identities are in a list they do not work when used outside of the original function. I believe this happens because the images are tied to their variable names and since those are all local tkinter garbage collects them resulting in my error which is "pyimagenumber does not exist." This is because the identity for a tkinter image is just "pyimage" and its corresponding number. My line of thinking is that I want to make all variable names that store images to be global without needing an extra line per image since that defeats the purpose of using a loop and list. Is there any way i can set the "vars()[var]" to be global while also giving it a value?

For any solutions I would like to avoid fundamental changes or using pillow. Any help is appreciated and if you have further questions about context please ask!

blu_pi
  • 1

2 Answers2

1

Simply move your empty list outside of your function. Also instead of for x in range(len(list)), use for x in something instead. It could be something like this:

import tkinter as tk

root = tk.Tk()
image_id = []

def image_creation():
    imlist = ["a","b","c","d"] #don't name it as list - it shadows the built in list
    for var in imlist: 
        image_id.append(tk.PhotoImage(file = var + ".gif"))

... #the rest of your code

root.mainloop()
Henry Yik
  • 22,275
  • 4
  • 18
  • 40
  • Appreciate the help and efficiency improvements but the same problem still occurs. pyimage12 does not exist so I still believe it is being garbage collected. I also had the list outside of the function in my code it was just not shown in my example. I thought not binding the image to a variable name could work but oh well... – blu_pi Dec 04 '19 at 18:54
  • Did you call mainloop more than once? – Henry Yik Dec 05 '19 at 00:17
0

There's no need to use vars(). Just create a dictionary in the global namespace and add your images to it. You can even use the original item from the list as the key.

Example:

global images
...
list = ["a","b","c","d"]
images = {}
for x in list:
    images[x] = tk.PhotoImage(file = var + ".gif")

Then, the image for "a" can be accessed at any time as images['a'].

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • It's a nice method but after testing it seems that images still get garbage collected... – blu_pi Dec 04 '19 at 20:01
  • @blu_pi: they will not get garbage-collected if `images` is global or an attribute of an object. – Bryan Oakley Dec 04 '19 at 20:32
  • If they aren't then somehow there must be another issue with my code. After using a dictionary to save the images with their filenames as keys they still "do not exist" when I try to use them outside of the function. The dictionary itself should also be global. – blu_pi Dec 04 '19 at 21:05
  • @blu_pi: if that is the case, please edit your question to include a [mcve]. We can only go on the code you posted, and this code is a proper replacement for the code in the question. – Bryan Oakley Dec 04 '19 at 22:27
  • Ultimately I think that the garbage collection of images is at fault. One way or another I have to prevent it from happening... I will try and make a MRE as soon as I can. – blu_pi Dec 05 '19 at 17:32
  • @blu_pi: it may be, but without knowing more about your code we can't say for sure. _this_ code will not have a problem with garbage collection. – Bryan Oakley Dec 05 '19 at 17:43
  • I can't even replicate the problem... I think it's the fact that I'm using the images inside of a class... Even if I create a new image on the line before it will throw a tkimage does not exist error... And outside of the class I can still use it. I found a similar error another had but the solutions were less than ideal. https://stackoverflow.com/questions/24274072/tkinter-pyimage-doesnt-exist – blu_pi Dec 09 '19 at 17:15
  • @blu_pi: if you can't replicate the problem, learn from what you've tried. Compare your attempts to solve this problem with your actual code to see what's different between the two. If you can't give us a way to replicate the problem, there's no way we can offer any better advice. – Bryan Oakley Dec 09 '19 at 17:18
  • In my attempts to replicate the code I have not had the function where I am using the images inside of the class since I did not think it was making a difference. I'm now almost certain that somehow this is causing the problem. Essentially the problem in the link is most likely exactly the problem I have. – blu_pi Dec 09 '19 at 17:21