pythoncustomtkinter

Set image (palplot) into Customtkinter button


How can I set an image (a palplot created with seaborn) into a Customtkinter button (CTkButton)?

In the following MWE, I created the button and the image but adding the image with image = image in the button definition does not work.

MWE

root = CTk()

# Create figure
image = plt.Figure()
ax = image.add_subplot()
# Create canvas to hold figure
canvas = FigureCanvasTkAgg(image, master=root)
canvas.get_tk_widget().grid(column=0, row=1)

ax.imshow(np.arange(500).reshape(1, 500),
          cmap=matplotlib.colors.ListedColormap(list(color_palette("flare", 500))),
          aspect="auto")
canvas.draw_idle()

# Create button
button = CTkButton(root, text="some button with an image", image = image)
button.grid(column=0, row=0)

root.mainloop()

Solution

  • According to the docs the image provided to CTkButton must be a tk.Photoimage. However, it can be a CTkImage as well.

    So one way to it is to directly convert the plt.figure to a PIL Image and then implement it as a CTkImage:

    CTkButton with transparent plot

    from PIL import Image
    from customtkinter import CTk, CTkButton, CTkImage
    from matplotlib import pyplot as plt
    
    # create plot and convert to PIL.Image
    plt.imshow([[1,0],[0,1]])
    canvas = plt.gcf().canvas
    canvas.draw()  # activate renderer for img extraction
    img = Image.frombytes('RGBA', canvas.get_width_height(), canvas.buffer_rgba())
    plt.close()
    
    # implement Image as a CTkImage in a CTkButton
    root = CTk()
    plot_img = CTkImage(light_image=img, dark_image=img, size=(200, 170))
    button = CTkButton(root, text="some button with an image", image=plot_img)
    button.grid(column=0, row=0)
    
    root.mainloop()