Search code examples
pythonpystray

Python pystray update_menu, use variable text for item


I want to change the text for an item variably. to do this, i tried to update the menu using update_menu(). unfortunately, this didn't work and i couldn't find anything more detailed in the pystray documentation. I hope you can help me. thank you.

from pystray import Icon as icon, Menu as menu, MenuItem as item
import PIL.Image

image = PIL.Image.new('RGB', (100, 100), 255)

adapter = 'before'
def test():
    global ps
    global adapter
    adapter = 'after'
    ps.update_menu()

ps = icon(name='name', icon=image, menu=menu(
        item(text='Adapter', action=menu(item(text='Test', action=test))),
        item(text=adapter, action=lambda: test()),
        )
    )
ps.run()

Solution

  • I've got to a similar problem earlier, I wanted to update the submenu while running.
    I made a version for what you wanted to adjust:

    def test(icon, this_item):
        global adapter
        adapter = 'after'
        global menu_items
        menu_items.pop() # remove last element, here containing 'adapter'
        # add new item with updated adapter value
        menu_items.append(item(text=adapter, action=test))
        icon.update_menu()
    
    menu_items = [
            item(text='Adapter', action=menu(item(text='Test', action=test))),
            item(text=adapter, action=test)
            ]
    
    ps = icon(name='name', icon=image, menu=menu(lambda: menu_items))
    ps.run()
    

    The MenuItem takes (*items) so giving it a list with items in a lambda function works to update it later.
    You have to alter the menu_items list to your needs and update.
    Couldn't figure out tho how to just adjust the text, with a lambda e.g. either.

    Found also this example #17, they changed the whole menu each time, but well...


    UPDATE: Here's what you wanted, cleaner than my previous answer:

    adapter = 'before'
    def test(icon, this_item):
        global adapter
        adapter = 'after'
        icon.update_menu()
    
    ps = icon(name='name', icon=image, menu=menu(
            item(text='Adapter', action=menu(item(text='Test', action=test))),
            item(lambda text: adapter, action=test)
            )
    )
    

    found here