Reputation: 11
I can display an image to the Label Widget without difficulty, however when I try to change the label widget image by using the '<>' bind to get a different image path string (which is then attached to a new PhotoImage class using the Retrieve_Image function), before being returned to the Label Widget. The program instead erases the current label widget content. (I know the treeview select is returning the correct image url because the Retrieve_Image function prints out the image string after each selection.
I have attempted to use a StringVar variable class to attempt to force the program to update the image string however this has been just as ineffective is using a regular string to store the image path.
I have altered the Retrieve_Image Function to return the image string instead of the PhotoImage object and instead assigned the label a new PhotoImage within the lambda function (This was also ineffective)
I am aware that the Tkinter PhotImage object clears when it is no longer in scope, however as the PhotoImage I am using was defined in the same main() function that it is called I am unsure why it keeps disappearing. Is it because it was called within a lambda function? and if so how can I alter my lambda function to ensure that my PhotoImage remains in scope? Or is the scope not the issue here?
Below I Have Embedded The Code Snippets I Believe To Be The Problem The Main Program (TransformersTCG_Deck_Builder.py) and other necessary data files Can Be Found At: https://github.com/perspace42/Transformers-TCG-Deck-Builder/blob/main/TransformersTCG_Deck_Builder.py
#Get Image From Selection
def Retrieve_Image(treeview):
'''This function requires the treeview as a parameter in order to retrieve the image location string of the selected Battle or Transformer Card'''
#Treeview Selection Returns a Tuple Which Must Be Converted Into a String To Turn Into An Image
selection_tuple = treeview.selection()
#Convert Tuple To String For Image Selection (image path is located at index 0 of the tuple)
selection_string = selection_tuple[0]
#Print To Verify What Program Has Retrieved
print(selection_string)
#Define Image amd Image Path
image = PhotoImage(file = selection_string)
return image
#set a variable class to display an image string in the card_preview_section frame
image_string = StringVar(card_preview_section,"Reckless-Charge.gif")
#set the image equal to the variable class string
card_image = PhotoImage(file = image_string.get())
image_label = Label(card_preview_section,image = card_image)
image_label.pack()
#Command Bindings For Treeview (Print Current Selection, and Display Image To Frame)
#Function Should Retrieve The Image (From TreeviewSelect), Then Display The Image Using a Label)
treeview_battle.bind('<<TreeviewSelect>>', lambda e: image_label.config(image = Retrieve_Image(treeview_battle)))
treeview_transformer.bind('<<TreeviewSelect>>', lambda e: image_label.config(image = Retrieve_Image(treeview_transformer)))
Upvotes: 0
Views: 40
Reputation: 46707
It is because the image is garbage collected as there is no variable referencing it.
Suggest to pass the label to the function and update the image of the label inside the function. Use an attribute of the label to store the reference of the image to avoid garbage collection:
def Retrieve_Image(treeview, label):
'''This function requires the treeview as a parameter in order to retrieve the image location string of the selected Battle or Transformer Card'''
#Treeview Selection Returns a Tuple Which Must Be Converted Into a String To Turn Into An Image
selection_tuple = treeview.selection()
#Convert Tuple To String For Image Selection (image path is located at index 0 of the tuple)
selection_string = selection_tuple[0]
#Print To Verify What Program Has Retrieved
print(selection_string)
#Define Image amd Image Path
image = PhotoImage(file = selection_string)
# update label
label.config(image=image)
label.image = image # store the reference of the image
return image # optional return
...
treeview_battle.bind('<<TreeviewSelect>>', lambda e: Retrieve_Image(treeview_battle, image_label))
treeview_transformer.bind('<<TreeviewSelect>>', lambda e: Retrieve_Image(treeview_transformer, image_label))
Upvotes: 0