C8H10N4O2
C8H10N4O2

Reputation: 19005

How to create Checkbuttons with images and text?

I am just getting started with tkinter widgets and am trying to create Checkbuttons with both images and text labels. Unfortunately, this cannot be done with basic Checkbutton(master=, image=, text=) as setting the image suppresses the text.

Here's a silly yet reproducible example of what I'm trying to do.

from tkinter import Tk, Frame, Checkbutton, Label
from PIL import ImageTk, Image
import requests

def getImgFromUrl(url): # using solution from : https://stackoverflow.com/a/18369957/2573061
   try:
       r = requests.get(url, stream=True)
       pilImage = Image.open(r.raw)
       phoImage = ImageTk.PhotoImage(pilImage)
       return phoImage
   except Exception as e:
       print('Error ' + repr(e) )
       return None


class AnimalPicker(Frame):
    def __init__(self):
        super().__init__()
        self.initUI()        
    
    def initUI(self):
        self.master.title("Animal Picker")

        
def main(): 
    root = Tk()
    root.geometry("250x450+300+300")
    app = AnimalPicker()
    
    imageUrls = ['http://icons.iconarchive.com/icons/martin-berube/flat-animal/64/dachshund-icon.png',
             'http://icons.iconarchive.com/icons/iconka/meow/64/cat-walk-icon.png',
             'http://icons.iconarchive.com/icons/sonya/swarm/64/Unicorn-icon.png']

    labels = ['Dog','Cat','Unicorn']
    
    images = [getImgFromUrl(x) for x in imageUrls]
    
    for i in range(len(images)):
        cb = Checkbutton(root, text=labels[i], image = images[i])
        cb.pack(anchor = 'w', padx=5,pady=5) 
    root.mainloop()  

if __name__ == '__main__':
    main()   

Gives me:

enter image description here

But I would like to have the labels "Cat", "Dog", and "Unicorn" either underneath or to the side of the images.

It's also important that the solution work for an arbitrary number of Checkbuttons, as in the for loop above.

Should I be using Grid and stacking these Checkbuttons next to Labels? I've managed to avoid learning it so far. Or is it easy to do with Pack?

Upvotes: 4

Views: 2982

Answers (1)

Nae
Nae

Reputation: 15335

I would like to have the labels ("Cat", "Dog", "Unicorn") either underneath or to the side of the images.

As suggested in Bryan's comment, this can be done by configuring compound option of Checkbutton.

Simply replace:

cb = Checkbutton(root, text=labels[i], image = images[i])

with:

cb = Checkbutton(root, text=labels[i], image = images[i], compound='left')

or set compound option to an element of ['bottom', 'center', 'left', 'right', 'top'] which is by default None:

cb['compound'] = 'top'

Below example produces an example for most Windows users:

import tkinter as tk
from PIL import Image, ImageTk

root = tk.Tk()

mypath = r"C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"
img = Image.open(mypath)
glb_img = ImageTk.PhotoImage(img)
tk.Checkbutton(root, text="Koala", image=glb_img, compound='top').pack()

root.mainloop()

Also it's worth noting that importing PIL is redundant for .png format, one could use either tk.PhotoImage(data=image_data) or tk.PhotoImage(file=image_file).

Upvotes: 5

Related Questions