Search code examples
pythontkintertkinter-button

Create tkinter buttons using a function


When i try to create buttons in a grid using a function (new_btn(r,c,btn)), the image on them gets removed and i cant click them exept for the last one. Its a 9*9 grid.

I tried it using loops but then i was not able to set the row an colum of the button, this is important because later on in this project only one button should have the image on.

def new_btn(r,c,btn):
    global photo
    # Create Buttons
    
    btn_1.update()
    print(btn)
    btn = Button(root, image=get_img(btn_1),)
    
    print(btn.winfo_height())
    btn.grid(row=r,column=c,sticky="NESW")
    return btn

btn_1 = Button(root,text="Button 1",)
btn_1.grid(row=0,column=0)
button_1 =  new_btn(0,0,"1")
button_2 =  new_btn(0,1,"2")
button_3 =  new_btn(0,2,"3")
button_4 =  new_btn(1,0,"4")
button_5 =  new_btn(1,1,"5")
button_6 =  new_btn(1,2,"6")
button_7 =  new_btn(2,0,"7")
button_8 =  new_btn(2,1,"8")
button_9 =  new_btn(2,2,"9")

def get_img(button):
    global resize_image
    global photo
    global abs_file_path
    img = Image.open(abs_file_path)

    resize_image = img.resize((button.winfo_height(), button.winfo_height()))
    photo = ImageTk.PhotoImage(resize_image)
    return photo

the get_image function just creates the file path to the image and sets its size to the size of the button. Note that in my code the get_img is above the other function if that is even relevant. The variable abs_file_path is created before it is just the path to the image.


Solution

  • Since you have used same global variable photo to store the image inside get_img(), so only the image of the last button will be shown because the other images are garbage collected due to no variable referencing them.

    You need to save the reference of the image for all the buttons by using an attribute of those buttons:

    def new_btn(r, c, btn):
        ...
        image = get_img(btn_1)
        btn = Button(root, image=image)
        btn.image = image # save the reference of image using an attribute of the button
        ...