0

im working on getting images on buttons instead of text for UI purposes, i have no experience working with images on UI, so im looking for some guidance, when i pass the image i get the error:

AttributeError: 'Open_Template' object has no attribute 'ImageTk'

Maybe someone can explain what am i missing to pass the ImageTk into the class?

from tkinter import *
from tkinter import messagebox
from PIL import ImageTk, Image
import datetime
import tkinter as tk
import webbrowser
import pytz
import openpyxl

class Main_App(tk.Tk):

    def __init__(self,*args,**kwargs):

        tk.Tk.__init__(self,*args,**kwargs)

        container = tk.Frame(self)
        container.pack(side="top",fill="both",expand=True)
        container.grid_rowconfigure(0, weight = 1)
        container.grid_columnconfigure(0, weight = 1)

        self.frames= {}

        for F in (test1,test2):

            frame = F(container, self)

            self.frames[F]=frame

            frame.grid (row=0, column = 0, sticky="nsew")

        self.show_frame(test1)

    def show_frame(self,cont):

        frame = self.frames[cont]
        frame.tkraise()

def SetMenu(self,parent,controller):

    Button1= tk.Button(self,relief='flat',command=lambda:controller.show_frame(test1))
    Button1.grid(column=0,row=0,sticky="nsew")
    Button1.config(image=self.ImageTk.PhotoImage(file ="image.gif"))


class test1(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)
        SetMenu(self,parent, controller)

class test2(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self,parent)
        SetMenu(self,parent, controller)

app=Main_App()
app.mainloop()

so, found a way to make it work. which is

Button1=Button(self,bg="white",relief='flat',command=lambda:controller.show_frame(test1))
Button1.grid(column=0,row=0,sticky="nsew")
self.ph_im4 = ImageTk.PhotoImage(file = "image.gif")
Button1.config(image=self.ph_im4)

but this kind of beats the purpose of what im trying to do, hence i would need to be able to load the image without the variable, or i would have to create like 500 variables to load and map every image manually

1
  • always put full error message (starting at word "Traceback") in question (not comment) as text (not screenshot). There are other useful information. Commented Feb 9, 2020 at 23:45

1 Answer 1

2

Why did you add self to ImageTk?

Button1.config(image=ImageTk.PhotoImage(file ="image.gif"))

If you need prevent garbage collector:

def SetMenu(self,parent,controller):

    self.button1_image=ImageTk.PhotoImage(file ="image.gif")
    Button1= tk.Button(self,relief='flat',command=lambda:controller.show_frame(test1))
    Button1.grid(column=0,row=0,sticky="nsew")
    Button1.config(image=self.button1_image)
    Button1.image=self.button1_image

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

5 Comments

if i dont pass it as self it does not load the image, it becomes a white square, i dont get an error from sublime text tho.
Your solution will create a local instance of ImageTk.PhotoImage inside SetMenu() function, and the instance will be garbage collected after SetMenu() is completed.
@JoshRodriguez The solution you mentioned in your post is one of the way. But I don't understand why you said it is not applicable to your design.
@acw1668 the idea here is to have a constructor, that assigns the image to the button. If i use the same variable to assign it to another button, the first one will have the image deleted, and button becomes a square of the bg color
Then you can attach the image reference to the assigned button. For example, if the button variable named btn, then btn.image = image.

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.