Search code examples
pythonbuttontkinterphotoimage

Python Tkinter Buttons just work with hardcoded Images


I am searching for a way to generate buttons with pictures for a little game. I am using Tkinter and a Grid layout in two ways but only one of them worked.

Here is the example code of the first (hardcoded) way to generate the Button with a picture:

currentImage=PhotoImage(file="Pictures//greenopen1s.gif")
currentImage = currentImage.subsample(x = "2", y = "2")
b2 = Button(root, image=currentImage)
b2.grid(column = 0, row = 1)

root.mainloop()

and here is the second generic way to generate the button with an image opened according to the argumented card:

b1 = Button(root, image=getImage(visibleCards[0])) 
b1.grid(column = 0, row = 0)

root.mainloop()

def getImage(card):
 currentPath = "Pictures//"
 currentColor = card.color
 currentPath = currentPath + currentColor
 currentShading = card.shading
 currentPath = currentPath + currentShading
 currentNumber = card.number
 currentPath = currentPath + currentNumber
 currentPath = currentPath + card.symbol
 currentPath = currentPath + ".gif"

 currentImage=PhotoImage(file=currentPath)
 currentImage = currentImage.subsample(x = "2", y = "2")

 return currentImage

The image algorithm to load the PhotoImage works correctly and the .gif files are in the correct location. I would like to know the difference between these two ways of getting the image.

Thank you very much


Solution

  • PhotoImage has trouble with garbage collection, so whatever variable gets set as a PhotoImage object can't get garbage collected. It's kind of odd and I'm not sure why it works that way, honestly.


    Try something like this:

    myImage = getImage(visibleCards[0])
    b1 = Button(root, image=myImage) 
    b1.grid(column = 0, row = 0)
    
    root.mainloop()
    
    def getImage(card):
        currentPath = "Pictures//"
        currentColor = card.color
        currentPath = currentPath + currentColor
        currentShading = card.shading
        currentPath = currentPath + currentShading
        currentNumber = card.number
        currentPath = currentPath + currentNumber
        currentPath = currentPath + card.symbol
        currentPath = currentPath + ".gif"
    
        currentImage=PhotoImage(file=currentPath)
        currentImage = currentImage.subsample(x = "2", y = "2")
    
        return currentImage