Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Make optionMenu with images in python tkinter

Here is another fantastic trick in tkinter: get images on an optionmenu (drop down, or combobox).

files/2024/listings/demo-optionmenu-with-images.py (Source)

#!/usr/bin/env python3
# Startdate: 2024-04-08-2 13:44
# Purpose: demo of the cool features of tkstackrpms
# Reference:
#    [python - Can I possibly put an image/label into an option box in Tkinter? - Stack Overflow](https://stackoverflow.com/questions/67334913/can-i-possibly-put-an-image-label-into-an-option-box-in-tkinter/67337760#67337760)
# demo 1: optionmenu with images and text
import tkinter as tk
import tkstackrpms as stk
class App(tk.Frame):
   def __init__(self, master):
      super().__init__(master)
      self.master.title("Demo of tkstackrpms features")
      imgicon = stk.get_scaled_icon("battery",24,"default", "","apps")
      self.master.tk.call("wm","iconphoto",self.master._w,imgicon)
      self.grid()
      self.options = ["Blue","Green","Yellow","Purple","Red"]
      # prepare set of images that corresponse to the options
      self.img_colors = []
      for i in self.options:
         t_image = tk.PhotoImage(width=16)
         t_image.put(i,to=(0,0,15,15))
         self.img_colors.append(t_image)
      self.opt_choice = tk.StringVar()
      self.opt_menu = tk.OptionMenu(self.master,self.opt_choice,*self.options)
      # indicatoron=False turns off the weird second-button item within the button.
      # minimize the padding so the box is not huge
      # takefocus allows navigation to this widget with Tab
      # compound means when an image is present, put it to the left of the text.
      self.opt_menu.config(indicatoron=False,padx=1,pady=1,takefocus=1,compound="left")
      self.opt_choice.set(self.options[0])
      self.opt_menu.grid(row=0,column=1)
      ow = self.opt_menu.nametowidget(self.opt_menu.menuname)
      x = 0
      for i in self.options:
         ow.entryconfigure(i,image=self.img_colors[x],compound="left")
         x += 1
      self.opt_choice.trace("w",self.set_selected_optmenu_entry)
      self.set_selected_optmenu_entry()
   def set_selected_optmenu_entry(self, arg1 = None, arg2 = None, arg3 = None):
      this_color = None
      x = 0
      for i in self.options:
         if self.opt_choice.get() == i:
            self.opt_menu.config(image=self.img_colors[x])
            break
         x += 1
# main
root = tk.Tk()
app_tk = App(root)
app_tk.mainloop()

So you have an optionMenu widget, where each option has an image associated with it. We're using very basic samples here; any real-world use of this trick would have a more complex list of images and options.

You can even set the front label of it to have an image, so you can view the currently selected image without having to open the drop-down.

Comments