0

Here is a part of my code, which loads images in a LabelFrame based on JSON objects from an external file. The code is inside a function (seems like that plays a role too, who knows).

# the black blackboard where images will be stored
black_background = tk.LabelFrame(pivote_tab, width=1340, height=290, bg="black")
black_background.grid(row=0, column=0, sticky="E")

# open the .json file
json_file = open('path/to/file.json', 'r')
json_data = json_file.read()

#the init position for image inside the blackboard
live_pc_position = 10

# make a loop for every object inside JSON
obj = json.loads(json_data)
        for i in range(int(len(obj))):
            os = (str(obj[i].get('operating_system')))

            if "Mac" in os:
                img_src = "image/macos_pc.png"
      
            elif "Win" in os and "10" in os:
                img_src = "image/windows_10.png"
            
            elif "Linux" in os:
                img_src = "image/linux_pc_image.png"
            
            else:
                img_src = "image/undetected_pc.png"

            # defining the image based on operating system and store it to the pc_image variable
            pc_image = PhotoImage(file=img_src)

            # adding the computer icon inside the blackboard
            computer_icon = Label(black_background, image=pc_image, bg="black")
            computer_icon.place(x=live_pc_position, y=10)

            # update values so the next image will load to the right
            live_pc_position = live_pc_position + 40

The script doesn't make any error, however for some reason only the first image is displayed when there are more images expected to be loaded, because JSON has more objects.

  • 1
    Since we don't have access to your `file.json`, it would be better if you created an example that used some hard-coded data instead of reading it from a file. There also appears to be an indentation problem. And, you keep overwriting your image variable with a new image. – Bryan Oakley Nov 24 '20 at 20:46
  • Each iteration of the loop changes the value of `pc_image` which affects the previous one. I think adding a `computer_icon.img = pc_image` will prevent the issue. – martineau Nov 24 '20 at 20:47
  • @JeffUK: The loop creates a new `computer_icon` each iteration of the loop. – martineau Nov 24 '20 at 20:48
  • @martineau can you provide an example code? I am not sure if I understand that. – Kleiton Kurti Nov 25 '20 at 00:45

3 Answers3

1

The problem with image is not loading in tkinter is almost always related to this.

At every loop you replace the value in pc_image and python garbage collector discards the Tkinter image object. The solution is to storage each Tkinter object in a different variable, which can be done with an object attribute or a list like the example bellow:

pc_images=[]
for i in range(int(len(obj))):
    ...
    
    pc_images.append(PhotoImage(file=img_src))
    
    Label(black_background, image=pc_images[i], bg="black").place(x=live_pc_position, y=10)
    
    live_pc_position = live_pc_position + 40
Flavio Moraes
  • 1,331
  • 1
  • 5
  • 16
1

This is what I was suggesting in my comment. See ALL CAPS COMMENT.

obj = json.loads(json_data)
for i in range(int(len(obj))):
    os = (str(obj[i].get('operating_system')))
    ...

    # defining the image based on operating system and store it to the pc_image variable
    pc_image = PhotoImage(file=img_src)

    # adding the computer icon inside the blackboard
    computer_icon = Label(black_background, image=pc_image, bg="black")
    computer_icon.img = pc_image  # KEEP A REFERENCE SO IMAGE IS NOT GARBAGE COLLECTED.
    computer_icon.place(x=live_pc_position, y=10)
    ...
martineau
  • 119,623
  • 25
  • 170
  • 301
  • Using your solution, only the first image is being displayed. The rest aren't being displayed. – Kleiton Kurti Nov 25 '20 at 01:01
  • It was mostly an educated guess. Please provide a [mre] in your question. – martineau Nov 25 '20 at 01:02
  • Ok, so I did a mix of your code and the one I answered, now it works. Thank you. I will edit my answer so the others can see it. – Kleiton Kurti Nov 25 '20 at 01:05
  • Glad to hear you got it figured out. Generally speaking you should almost always create the extra reference. See accepted answer to [Why does Tkinter image not show up if created in a function?](https://stackoverflow.com/questions/16424091/why-does-tkinter-image-not-show-up-if-created-in-a-function) – martineau Nov 25 '20 at 01:10
0

The script is from @flavio-moraes logically works, however with a mix of the answers I got, I made the final script which fullfills my needs.

pc_images=[]
for i in range(int(len(obj))):
    ...
    pc_images.append(PhotoImage(file=img_src))

live_pc_position = 10
for pc in pc_images:
    #create the image
    computer_icon = Label(black_background, image=pc, bg="black")
    computer_icon.img = pc_images
    computer_icon.place(x=live_pc_position, y=10)
        
    # update values so the next image will load to the right
    live_pc_position = live_pc_position + 40