OpaxZity
OpaxZity

Reputation: 13

How to make each button display a different image on click using tkinter (python)

I am creating a GUI with a ".grid" of buttons. And I want to make each of those buttons display a different image on press. So when I click button 1, it will bring up "image1", on the bottom of the buttons. When I click button 2, it will bring up "image2" and etc.

Through some research, I was able to make the buttons run a function that takes in a parameter through the method below. However, I can't seem to make the button display the image. rather, it just makes an empty white space underneath the buttons, when I press any buttons.

Disclaimer: - I do not want there to be loads of images, there will only be 1 image, and it will change depending on what button i press.

Here's the code:

from tkinter import *

def funct(numimg):
    image = PhotoImage(file="image"+str(numimg)+".png")   
    label = Label(image=image)
    label.grid(row = row_no+1, column = 0, columnspan = num_of_cols)

def make_funct(number):
    return (lambda: funct(number))

root= Tk()
row_no = -1
buttons = []
num_of_cols = 3
root.resizable(0, 0)
numfiles = 6

for x in range(0, numfiles):
    if(x % num_of_cols is 0):
        row_no+=1

    buttons.append(Button(root, text = "Button "+str(x), bg = '#4098D3', width = 30,height = 13,command = make_funct(x)))
    buttons[x].grid(row = row_no, column = x % num_of_cols)

root.mainloop()

So my question is, how do you make each individual button, display a different image when it is pressed? this program right here just leaves an empty white space in replace of the image, and the image is not shown.

Upvotes: 1

Views: 2641

Answers (1)

fhdrsdg
fhdrsdg

Reputation: 10532

There are two major problems with the code you posted.

The first is basically the same as in this question: Why does Tkinter image not show up if created in a function?. You should keep a reference to the PhotoImage object, else it will be garbage collected and it will not show.

The second is that you create a new Label on every button click. You should only make one Label and change the image with the label.config() method.

I would (without wrapping your GUI in a class, which might be a nicer solution) load all images on initialization, save them in a list as attribute of the label and only change the image upon a button click.

I also removed your make_funct function and replaced it with a lambda, which is the most used way to pass variables to a function on callback.

from tkinter import *

def funct(numimg):
    label.config(image=label.images[numimg])

root= Tk()
row_no = -1
buttons = []
num_of_cols = 3
root.resizable(0, 0)
numfiles = 3

for x in range(0, numfiles):
    if(x % num_of_cols is 0):
        row_no+=1

    buttons.append(Button(root, text = "Button "+str(x), bg = '#4098D3', width = 30,height = 13, command = lambda n=x: funct(n)))
    buttons[x].grid(row = row_no, column = x % num_of_cols)

label = Label(root)
label.grid(row = row_no+1, column = 0, columnspan = num_of_cols)

label.images=[]

for x in range(0, numfiles):
    label.images.append(PhotoImage(file="image"+str(x)+".png"))

root.mainloop()

Upvotes: 1

Related Questions