Ad

Tkinter Create_image() Retains PNG Transparency But Button(image) Does Not

TkVersion = 8.6, Python version 3.7.3

Im trying to create a button in python with tkinter using a PNG image. The transparent corners of the image are transparent depending on which widget I use. It seems canvas.create_image is the only widget retaining the transparency.

First I added the image on a canvas using create_image(0,0, image=button) and it works fine - the rounded corners are transparent.

But then when I try to implement it as an actual button using Button() and create_window() widgets, the corners are filled with white.

button = ImageTk.PhotoImage(file="button.png")

canvas = tk.Canvas(width=200, heigh=200, borderwidth=0, highlightthickness=0)
canvas.grid()
canvas.create_rectangle(0,0,199,199, fill="blue")

canvas.create_image(0,0, image=button, anchor="nw")

works[]

button = ImageTk.PhotoImage(file="button.png")

canvas = tk.Canvas(width=200, heigh=200, borderwidth=0, highlightthickness=0)
canvas.grid()
canvas.create_rectangle(0,0,199,199, fill="blue")

buttonWidget = tk.Button(root, image=button)
canvas.create_window(0,0, window=buttonWidget, anchor="nw")

doesnt work

How can I make the PNG button corners transparent?

Here is also the button image: button

Ad

Answer

You can make your own custom button class inherited from canvas and use it just like you use Button(). I made one for you hopefully you find it helpful.

Custom Button Class:

Save this class in a separate file as imgbutton.py and then import it to your main file. Also make sure it is in the same directory as the main file is in. Or you can just keep it on the top of the main file after your imports.

import tkinter as tk

class Imgbutton(tk.Canvas):

    def __init__(self, master=None, image=None, command=None, **kw):

        # Declared style to keep a reference to the original relief
        style = kw.get("relief", "groove")        

        if not kw.get('width') and image:
            kw['width'] = image.width()
        else: kw['width'] = 50

        if not kw.get('height') and image:
            kw['height'] = image.height()
        else: kw['height'] = 24

        kw['relief'] = style
        kw['borderwidth'] = kw.get('borderwidth', 2)
        kw['highlightthickness'] = kw.get('highlightthickness',0)

        super(Imgbutton, self).__init__(master=master, **kw)

        self.set_img = self.create_image(kw['borderwidth'], kw['borderwidth'], 
                anchor='nw', image=image)

        self.bind_class( self, '<Button-1>', 
                    lambda _: self.config(relief='sunken'), add="+")

        # Used the relief reference (style) to change back to original relief.
        self.bind_class( self, '<ButtonRelease-1>', 
                    lambda _: self.config(relief=style), add='+')

        self.bind_class( self, '<Button-1>', 
                    lambda _: command() if command else None, add="+")

Here is an Example how to use it

import tkinter as tk
from imgbutton import Imgbutton    # Import the custom button class

root = tk.Tk()
root['bg'] = 'blue'

but_img = tk.PhotoImage(file='button.png')

but = Imgbutton(root, image=but_img, bg='blue', 
            command=lambda: print("Button Image"))
but.pack(pady=10)

root.mainloop()
Ad
source: stackoverflow.com
Ad