detroitwilly
detroitwilly

Reputation: 821

Issue with Button Images in ttk/Python

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

Upvotes: 1

Views: 5182

Answers (1)

furas
furas

Reputation: 142681

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

Upvotes: 9

Related Questions