Yes it is possible. For instance, you can
Use the postcommand
option of the Optionmenu's menu to change the image on the button to an arrow pointing up.
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:
Create 'up' and 'down' elements from the images
style.element_create('up', 'image', imgUp)
style.element_create('down', 'image', imgDown)
Create 'up.TMenubutton' and 'down.TMenubutton' layouts from the 'TMenubutton' layout (obtain with style.layout('TMenubutton')
) by replacing 'Menubutton.indicator' by 'up' or 'down'.
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()