1
import tkinter as tk
from PIL import ImageTk, Image

window = tk.Tk()
window.geometry("300x300")
canvas = tk.Canvas(window, width=300, height=300,bg="red")
canvas.pack()

class Button():
    def __init__(self, x, y, canv):
        self.img = ImageTk.PhotoImage(Image.open("Hover.png"))
        canv.create_image(x, y, image=self.img, anchor="nw")

Button(0, 0, canvas)

window.mainloop()

I am trying to display an image in python using the tkinter canvas option. However, if I input it in a class, like below, it doesn't give an error but also doesn't show my image. Pls solve this for me without put the canvas inside of the class

1
  • 1
    You need to keep a reference of the instance of the class to avoid garbage collection, like img1 = Button(...). Commented May 26, 2024 at 1:16

3 Answers 3

1
  • Make sure the image path is correct.

  • Add self.canv = canv to the __init__:

import tkinter as tk
from PIL import ImageTk, Image


class Button:
    def __init__(self, x, y, canv):
        self.img = ImageTk.PhotoImage(Image.open("Hover.png"))
        self.canv = canv
        self.canv.create_image(x, y, image=self.img, anchor="nw")
        self.canv.image = self.img

window = tk.Tk()
window.geometry("300x300")
canv = tk.Canvas(window, width=300, height=300, bg="red")
canv.pack()

Button(0, 0, canv)

window.mainloop()

Style

You can also style it by setting positions and scale:

import tkinter as tk
from PIL import ImageTk, Image


class Button:
    def __init__(self, x, y, canv, img_path, scale=100):
        self.canv = canv
        self.img_path = img_path
        self.scale = scale / 100.0
        self.set_scale()
        self.border = self.canv.create_rectangle(
            x - 5,
            y - 5,
            x + self.img.width() + 5,
            y + self.img.height() + 5,
            outline="white", width=5)

        self.img_id = self.canv.create_image(x, y, image=self.img, anchor="nw")

        self.canv.tag_bind(self.img_id, "<Enter>", self.hover)
        self.canv.tag_bind(self.img_id, "<Leave>", self.unhover)

    def set_scale(self):
        orig = Image.open(self.img_path)
        w, h = orig.size
        sw, sh = int(w * self.scale), int(h * self.scale)
        resized = orig.resize((sw, sh), Image.LANCZOS)
        self.img = ImageTk.PhotoImage(resized)

    def set_pos(self, x, y):
        self.canv.coords(self.img_id, x, y)
        self.canv.coords(self.border, x - 5, y - 5, x + self.img.width() + 5, y + self.img.height() + 5)

    def hover(self, event):
        self.canv.itemconfig(self.border, outline="yellow")

    def unhover(self, event):
        self.canv.itemconfig(self.border, outline="white")


window = tk.Tk()
window.geometry("300x300")
canv = tk.Canvas(window, width=300, height=300, bg="red")
canv.pack()

button = Button(0, 0, canv, "hover.png", 30)
button.set_pos(25, 25)

window.mainloop()

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

Comments

1

I am trying to display an image in python using the tkinter canvas option. However, if I input it in a class, like below, it doesn't give an error but also doesn't show my image

The problem can be fixed.

Just add line 13.

canv.image = self.img

Snippet:

class Button():
    def __init__(self, x, y, canv):
        self.img = ImageTk.PhotoImage(Image.open("Hover.png"))
        canv.create_image(x, y, image=self.img, anchor="nw")
        canv.image = self.img

Screenshot:

enter image description here

Comments

1

Since there is no variable referencing the class instance, the class instance will be garbage collected and so to the image created inside the class instance.

Simply keep references to the class instances:

img1 = Button(0, 0, canvas)
img2 = Button(50, 50, canvas)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.