Jakob
Jakob

Reputation: 2005

Keep a menu open in Tkinter

I want to keep a menu cascade open, after a command button within the cascade is clicked. So it basically only closes when the user clicks anywhere else (like it would normally too). Can't seem to find a proper option or a method to open said menu in the callback. The invoke() function only works on buttons wihtin the cascade right? How would you go about that?

Upvotes: 5

Views: 2312

Answers (1)

John Gaines Jr.
John Gaines Jr.

Reputation: 11534

Yes, I know this was asked a long time ago, but I was curious if there was any way to accomplish this with tkinter, so I fiddled about for a while and figured out how to do it. I was unable to come up with a way to properly place the persistent menu where it was when it originally opened, but I have managed to make it persist in any location you request (I use upper-left corner of root window). And yes, I know this isn't a nice proper class based implementation, but I was just going for as simple a test as I could write without obscuring it with too many extraneous details.

try:
    from tkinter import *
    from tkinter.ttk import *
except:
    from Tkinter import *
    from ttk import *

root = Tk()
var = StringVar()

def menu_click(menu, item):
    global root
    var.set(item)
    menu.post(root.winfo_rootx(), root.winfo_rooty())

root.option_add('*tearOff', False)  # remove tearoff from all menus
Label(root, textvariable=var).pack()  # just to give menu clicks some feedback
root.geometry('400x300')
menubar = Menu(root)
root['menu'] = menubar
menu_test = Menu(menubar)
menubar.add_cascade(menu=menu_test, label='Test')
menu_test.add_command(label='One', command=lambda: menu_click(menu_test, 'One'))
menu_test.add_command(label='Two', command=lambda: menu_click(menu_test, 'Two'))
menu_test.add_command(label='Three', command=lambda: menu_click(menu_test, 'Three'))
menu_cas = Menu(menu_test)
menu_test.add_cascade(menu=menu_cas, label='Four')
menu_cas.add_command(label='One', command=lambda: menu_click(menu_cas, 'Fourty One'))
menu_cas.add_command(label='Two', command=lambda: menu_click(menu_cas, 'Fourty Two'))
menu_cas.add_command(label='Three', command=lambda: menu_click(menu_cas, 'Fourty Three'))
root.mainloop()

Upvotes: 3

Related Questions