Python Forum
[Tkinter] image inside button
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] image inside button
#1
I am trying to add image inside a button. It is empty, I have the image in the exact location and no errors.

    photo1 = PhotoImage(file="imgs/math/1.png")
    photoimage1 = photo1.subsample(3, 3)
    Button(exam_started,image=photoimage1).pack()
Thanks
Reply
#2
My guess is you are doing something like this:
import pathlib
import tkinter as tk

IMAGE_DIR = pathlib.Path(__file__).parent

def make_image_button(parent, image_file):
    image1 = tk.PhotoImage(file=IMAGE_DIR/image_file)
    tk.Button(parent, image=image1).pack()
    
ROOT = tk.Tk()
make_image_button(ROOT, 'dice1.png')
ROOT.mainloop()
This displays an empty button, but with one small change it works.
"""A dice game"""
import pathlib
import tkinter as tk

image1 = None
IMAGE_DIR = pathlib.Path(__file__).parent

def make_image_button(parent, image_file):
    global image1
    image1 = tk.PhotoImage(file=IMAGE_DIR/image_file)
    tk.Button(parent, image=image1).pack()
    
ROOT = tk.Tk()
make_image_button(ROOT, 'dice1.png')
ROOT.mainloop()
The reason the image disappears in the upper code is because the only reference to the image object is a local variable in function "make_image_button". When the function exits the image has no references and is garbage collected. In the lower code we fix that problem by assigning a global variable to reference the image.

Does that fix the problem?
rwahdan likes this post
Reply
#3
(Jul-12-2021, 06:26 PM)deanhystad Wrote: Does that fix the problem?

Yes it sure did thanks for pointing out global variables.
Reply
#4
You can avoid using global and keep a reference to the image on the button object.
photo1 = tk.PhotoImage(file="imgs/math/1.png")
btn = tk.Button(exam_started,image=photoimage1)
btn.pack()
btn.photo1 = photo1
rwahdan likes this post
Reply
#5
It doesn't have to be a global variable, it just has to be a variable that isn't thrown away. In fact it really shouldn't be a global variable. Global variables are BAD, BAD, BAD. Only use them when you must.

If you want to make buttons with images It may work better for you if you make a new button class that keeps track of it's images.
import pathlib
import tkinter as tk

IMAGE_DIR = pathlib.Path(__file__).parent

class ImageButton(tk.Button):
    """I am a button with an image"""
    def __init__(self, parent, image_file, *args, **kvargs):
        self.image = tk.PhotoImage(file=IMAGE_DIR/image_file)
        super().__init__(parent, *args, image=self.image, **kvargs)

ROOT = tk.Tk()
ImageButton(ROOT, 'dice1.png').pack()
ROOT.mainloop()
All this class does is add an instance variable to Button that references the image so it isn't garbage collected.

If you don't like making a class, you can always stuff the image variable into the Button object.
import pathlib
import tkinter as tk

IMAGE_DIR = pathlib.Path(__file__).parent

ROOT = tk.Tk()
image = tk.PhotoImage(file=IMAGE_DIR/'dice1.png')
button = tk.Button(ROOT, image=image)
button.image = image  # Add image instance variable to button
button.pack()
ROOT.mainloop()
I've seen a lot of code online that does this. I don't know how many of the authors knew what they were doing and why it worked. Essentially it does the same thing as the subclass solution, but in an informal way. Python classes act a lot like dictionaries and you can add attributes to them like you can add entries to a dictionary. The code above adds an attributed named "image" to the button object. This prevents the image reference count from going to zero and the image being garbage collected. Normally a tkinter Button doesn't have an image attribute. The code below raises an exception when trying to access "button.image".
import tkinter as tk

IMAGE_DIR = pathlib.Path(__file__).parent

ROOT = tk.Tk()
image = tk.PhotoImage(file=IMAGE_DIR/'dice1.png')
button = tk.Button(ROOT, image=image)
print(button.image)
button.pack()
ROOT.mainloop()
Output:
AttributeError: 'Button' object has no attribute 'image'
rwahdan likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [Tkinter] Why does the image for the button not appear? finndude 4 2,047 Oct-21-2021, 06:41 PM
Last Post: deanhystad
  tkinter showing image in button rwahdan 3 5,516 Jun-16-2021, 06:08 AM
Last Post: Yoriz
  [Kivy] Acces atributes from a button defined in a class inside the .kv Tomli 2 2,052 Jun-10-2021, 01:05 AM
Last Post: Tomli
  tkinter button image Nick_tkinter 4 3,954 Mar-04-2021, 11:33 PM
Last Post: deanhystad
  Problem about image and button scotesse 5 2,877 Apr-27-2020, 10:09 AM
Last Post: scotesse
  [PyQt] Problem how to click a button inside a group box? mart79 2 3,375 Aug-05-2019, 01:21 PM
Last Post: mart79
  Button with Image Icon Friend 2 6,762 Jul-25-2019, 09:39 AM
Last Post: Friend
  [PySimpleGui] How to alter mouse click button of a standard submit button? skyerosebud 3 4,947 Jul-21-2019, 06:02 PM
Last Post: FullOfHelp
  [Tkinter] Resizing image inside Canvas (with Canvas' resize) Gupi 2 25,021 Jun-04-2019, 05:05 AM
Last Post: Gupi
  Simple Button click on image file to create action? jpezz 4 6,789 Mar-27-2019, 10:08 PM
Last Post: jpezz

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020