1

I'm messing around with ttk/tkinter in Python (3.5), and I'm having some issues with buttons (specifically, ttk.Button).

No matter what I try, I cannot for the life of me get an image to show up on a button.

I have the following code:

from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk

class Example(ttk.Frame):
    def __init__(self, master):
        ttk.Frame.__init__(self, master)
        master.title('Button Test')

        self.configure(padding='10 10 10 10')
        self.grid(column=0, row=0, sticky=(N, E, W, S))

        buttonImage = Image.open('play.png')
        buttonPhoto = ImageTk.PhotoImage(buttonImage)

        myButton = ttk.Button(self, image=buttonPhoto, padding='10 10 10 10')
        myButton.grid(column=1, row=1, sticky=(E, W))

if __name__ == "__main__":
    root = Tk()
    example = Example(root)
    root.mainloop()

This is an amalgamation of examples I found here, here, and from users here on StackOverflow.

Thanks in advance for any ideas/insight.

-Sean

1
  • PhotoImage has problem with garbage collector which removes image if it is assigned to local variable. Assign image to class variable self.buttonPhoto Commented Jan 25, 2017 at 23:10

1 Answer 1

9

PhotoImage has problem with garbage collector which removes image if it is assigned to local variable.

Assign image to class variable self.buttonPhoto

self.buttonPhoto = ImageTk.PhotoImage(buttonImage) 

Full:

from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk

class Example(ttk.Frame):
    def __init__(self, master):
        ttk.Frame.__init__(self, master)
        master.title('Button Test')

        self.configure(padding='10 10 10 10')
        self.grid(column=0, row=0, sticky=(N, E, W, S))

        buttonImage = Image.open('play.png')

        # use self.buttonPhoto
        self.buttonPhoto = ImageTk.PhotoImage(buttonImage) 

        # use self.buttonPhoto
        myButton = ttk.Button(self, image=self.buttonPhoto, padding='10 10 10 10')
        myButton.grid(column=1, row=1, sticky=(E, W))

if __name__ == "__main__":
    root = Tk()
    example = Example(root)
    root.mainloop()

Or assign image to other object - it should stop garbage collector too.

ie.

    myButton.image = buttonPhoto

Full:

from tkinter import *
from tkinter import ttk
from PIL import Image, ImageTk

class Example(ttk.Frame):
    def __init__(self, master):
        ttk.Frame.__init__(self, master)
        master.title('Button Test')

        self.configure(padding='10 10 10 10')
        self.grid(column=0, row=0, sticky=(N, E, W, S))

        buttonImage = Image.open('tplay.png')
        buttonPhoto = ImageTk.PhotoImage(buttonImage)

        myButton = ttk.Button(self, image=buttonPhoto, padding='10 10 10 10')
        myButton.grid(column=1, row=1, sticky=(E, W))
        # assign image to other object
        myButton.image = buttonPhoto

if __name__ == "__main__":
    root = Tk()
    example = Example(root)
    root.mainloop()

See Note at the end of page The Tkinter PhotoImage Class

Sign up to request clarification or add additional context in comments.

2 Comments

That did it. Very good information to have, and also explains part of one of the examples I cited. Thanks, furas.
This works but I have a question. I Googled many references but didn't find option padding for ttk.Button. Why does it work here? Could you explain a bit more? Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.