python-3.xtkinterdebian-buster

get submenu tkinter object


Having nested (with sub menus added by .add_cascade) tkinter Menu object, is it possible to get the sub menu object?

I tried (menu_lab.py):

def main(root):
    top = tk.Menu(root)
    root.config(menu=top)
    top.add_command(label='Get sub', command=lambda t=top: get_sub(t))
    sub = tk.Menu(top)
    sub.add_command(label='Glider', command=lambda: print('Glider'))
    top.add_cascade(label='Insert', menu=sub)
    get_sub(top)


def get_sub(top):
    for i in range(top.index(tk.END) + 1):
        try:
            if top.entrycget(i, 'label') == 'Insert':
                sub = top.entrycget(i, 'menu')
                print(f'{sub = }')
        except tk.TclError:  # unknown option "-label"
            continue


if __name__ == '__main__':
    root = tk.Tk()
    main(root)
    root.mainloop()

it prints:

$ python menu_lab.py
sub = '.!menu.!menu'

Using Python 3.9.2, Debian 11


Solution

  • The cget method returns the internal name of the widget. You can use the universal widget method nametowidget to convert that name to the actual widget object:

    sub = top.entrycget(i, 'menu')
    menu = top.nametowidget(sub)