I have managed to change the indicator within the optionmenu box through using indicatoron=0, compound=RIGHT, image=dropImg, width=120 but I am now trying to change the arrow to point up when the box is clicked and the list of elements are shown. For instance: I tried activeindicatoron = 0 but this doesn't work. Does anyone have any ideas on whether this is possible in tkinter?

Thanks, Jacob

1

There are 1 best solutions below

0
On BEST ANSWER

Yes it is possible. For instance, you can

  1. Use the postcommand option of the Optionmenu's menu to change the image on the button to an arrow pointing up.

  2. Use a binding to the <Unmap> event of the Optionmenu's menu to revert to the arrow pointing down when the menu disappears.

Here is an example:

import tkinter as tk
root = tk.Tk()

# up and down images
down =b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x07\x08\x06\x00\x00\x008G|\x19\x00\x00\x00\tpHYs\x00\x00\x10\x9b\x00\x00\x10\x9b\x01t\x89\x9cK\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x00OIDAT\x18\x95\x95\xce\xb1\x0e@P\x0cF\xe1\xefzI\x8fc$\x12\x111\x19\xec\x9e\x12\xcb\x95 A\x9d\xa4K\xff\x9e\xb6\t\x13J\xffX \xa1\xc7\x16\xac\x19\xc5\xb1!*\x8fy\xf6BB\xf7"\r_\xff77a\xcd\xbd\x10\xedI\xaa\xa3\xd2\xf9r\xf5\x14\xee^N&\x14\xab\xef\xa9\'\x00\x00\x00\x00IEND\xaeB`\x82'
up = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x07\x08\x06\x00\x00\x008G|\x19\x00\x00\x00\tpHYs\x00\x00\x10\x9b\x00\x00\x10\x9b\x01t\x89\x9cK\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x00\\IDAT\x18\x95\x8d\xd0A\n\x830\x14\x06\xe1/z,\x0f\xd2#\x19\\\xb4\x08Ep\xe1\xbe\xd7\xe8\xc5\xd2n\x12\x11%\x92\x81\xd9<\xfe\xd9\xbc^\x9d\x88\x01\xdf\x9b\xcd\x85\t?$\x8c\xadQ\xccQ1\xe5[\x95\x80\xe7)::\xd7\xa2\xd7MT|\xe7\xed\x1e-\rQqC\x17\xb0\xe2\xd1\xfa\x80\xcc\xe7\x0fO\xbe&\x9dv\xae\xef\x97\x00\x00\x00\x00IEND\xaeB`\x82'
imgDown = tk.PhotoImage(master=root, data=down)
imgUp = tk.PhotoImage(master=root, data=up)

# create option menu
var = tk.StringVar(root, 'a')
option = tk.OptionMenu(root, var, *list('abcde'))
option.configure(indicatoron=0, compound=tk.RIGHT, image=imgDown, width=120)

# configure menu
menu = option['menu']
menu.configure(postcommand=lambda: option.configure(image=imgUp))
menu.bind('<Unmap>', lambda ev: option.configure(image=imgDown))
option.pack()

root.mainloop()

TTK version

It is also possible to achieve this when using a ttk.OptionMenu and I think it look nicer because the arrow really replaces the indicator instead of being in the place of the image. This can be done by modifying the layout of the TMenubutton style:

  1. Create 'up' and 'down' elements from the images

    style.element_create('up', 'image', imgUp)
    style.element_create('down', 'image', imgDown)
    
  2. Create 'up.TMenubutton' and 'down.TMenubutton' layouts from the 'TMenubutton' layout (obtain with style.layout('TMenubutton')) by replacing 'Menubutton.indicator' by 'up' or 'down'.

  3. Use postcommand and <Unmap> to change the style of the Menubutton.

Here is the code:

import tkinter as tk
from tkinter import ttk
root = tk.Tk()

# images
down = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x07\x08\x06\x00\x00\x008G|\x19\x00\x00\x00\tpHYs\x00\x00\x10\x9b\x00\x00\x10\x9b\x01t\x89\x9cK\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x00OIDAT\x18\x95\x95\xce\xb1\x0e@P\x0cF\xe1\xefzI\x8fc$\x12\x111\x19\xec\x9e\x12\xcb\x95 A\x9d\xa4K\xff\x9e\xb6\t\x13J\xffX \xa1\xc7\x16\xac\x19\xc5\xb1!*\x8fy\xf6BB\xf7"\r_\xff77a\xcd\xbd\x10\xedI\xaa\xa3\xd2\xf9r\xf5\x14\xee^N&\x14\xab\xef\xa9\'\x00\x00\x00\x00IEND\xaeB`\x82'
up = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00\x00\x07\x08\x06\x00\x00\x008G|\x19\x00\x00\x00\tpHYs\x00\x00\x10\x9b\x00\x00\x10\x9b\x01t\x89\x9cK\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x00\\IDAT\x18\x95\x8d\xd0A\n\x830\x14\x06\xe1/z,\x0f\xd2#\x19\\\xb4\x08Ep\xe1\xbe\xd7\xe8\xc5\xd2n\x12\x11%\x92\x81\xd9<\xfe\xd9\xbc^\x9d\x88\x01\xdf\x9b\xcd\x85\t?$\x8c\xadQ\xccQ1\xe5[\x95\x80\xe7)::\xd7\xa2\xd7MT|\xe7\xed\x1e-\rQqC\x17\xb0\xe2\xd1\xfa\x80\xcc\xe7\x0fO\xbe&\x9dv\xae\xef\x97\x00\x00\x00\x00IEND\xaeB`\x82'
imgDown = tk.PhotoImage(master=root, data=down)
imgUp = tk.PhotoImage(master=root, data=up)

# style
style = ttk.Style(root)
style.theme_use('clam')
style.element_create('up', 'image', imgUp)
style.element_create('down', 'image', imgDown)

style.layout('up.TMenubutton', [('Menubutton.border',
  {'sticky': 'nswe',
   'children': [('Menubutton.focus',
     {'sticky': 'nswe',
      'children': [('Menubutton.up', {'side': 'right', 'sticky': ''}),  # replace the indicator by up arrow
       ('Menubutton.padding',
        {'expand': '1',
         'sticky': 'we',
         'children': [('Menubutton.label',
           {'side': 'left', 'sticky': ''})]})]})]})])

style.layout('down.TMenubutton', [('Menubutton.border',
  {'sticky': 'nswe',
   'children': [('Menubutton.focus',
     {'sticky': 'nswe',
      'children': [('Menubutton.down', {'side': 'right', 'sticky': ''}),  # replace the indicator by down arrow
       ('Menubutton.padding',
        {'expand': '1',
         'sticky': 'we',
         'children': [('Menubutton.label',
           {'side': 'left', 'sticky': ''})]})]})]})])

var = tk.StringVar(root, 'a')
option = ttk.OptionMenu(root, var, *list('abcde'))
option.configure(style='down.TMenubutton')
menu = option['menu']
menu.configure(postcommand=lambda: option.configure(style='up.TMenubutton'))
menu.bind('<Unmap>', lambda ev: option.configure(style='down.TMenubutton'))
option.pack()

root.mainloop()