Home > Net >  How do you open a submenu automatically in a tkinter menu?
How do you open a submenu automatically in a tkinter menu?

Time:04-12

I know that menu.tk_popup() can be used to open a context menu at a certain coordinate, but don't know how to open a submenu out of it too, if that makes sense. This is the code I made:

import tkinter as tk

root = tk.Tk()
root.geometry("500x400")

def contextMenu(e, openCascade=False):
    my_menu2 = tk.Menu(root, tearoff=False)
    my_menu2.add_command(label="command2")
    my_menu = tk.Menu(root, tearoff=False)
    my_menu.add_cascade(label="cascade1", menu=my_menu2)
    my_menu.add_command(label="command1")
    my_menu.tk_popup(e.x_root, e.y_root)
    if openCascade:
        my_menu2.tk_popup(e.x_root, e.y_root) #doesn't work

root.bind("<Button-3>", contextMenu)
root.bind("<Button-2>", lambda e: contextMenu(e=e, openCascade=True))

root.mainloop()

The code basically makes a window that when right-clicked (< Button-3> bind) will display the first menu (my_menu) which has a cascade (cascade1) which when manually runned (i.e. clicked), displays a submenu (my_menu2) as shown below. enter image description here

The problem with this is not the right-clicking, but the middle-clicking (< Button-2> bind) does not work how I intended. When I middle-click, I tried to make it so it displays both the menus (my_menu, my_menu2), but my attempt just displays both but with the first menu overlapping, so the other doesn't show.

So the question is, how do I make it so when middle-clicking, it opens the first menu AND then automatically runs the cascade, as if it was clicked? If you do not understand what I explained please do not hesitate to ask.

CodePudding user response:

So the question is, how do I make it so when middle-clicking, it opens the first menu AND then automatically runs the cascade, as if it was clicked?

Considering this answer by Bryan Oakley and the documentation available on the internet, there is no way for making a menu and a submenu visible simultaneously. "That's just not how Tkinter menus are designed to work."

You will have to create a customized menu bar without using the widget tk.Menu.


When I middle-click, I tried to make it so it displays both the menus (my_menu, my_menu2), but my attempt just displays both but with the first menu overlapping, so the other doesn't show.

They are not overlapping. Even if you add some gap to the x-y values using some integers, still you won't be seeing the second menu.

The reason is that using tk_popup or post will make the menu appear on the screen for sure, but then the program's focus gets shifted to the user's mouse and keyboard. So, until the user clicks out of the focus of that menu, the program won't be coming out to execute the next lines of the function (in which you are calling the tk_popup for the submenu.)

Here you can see what I mean:

    .
    .
    .
    my_menu.add_command(label="command1")
    
    print("Before my_menu popup")
    my_menu.tk_popup(e.x_root, e.y_root)
    print("After my_menu popup")
    if openCascade:
        print("Before my_menu2 popup")
        my_menu2.tk_popup(e.x_root 30, e.y_root 50) #added some gap to show they are not overlapping
        print("After my_menu2 popup")

root.bind("<Button-3>", contextMenu)
root.bind("<Button-2>", lambda e: contextMenu(e,True))

root.mainloop()

So, when you are middle-clicking (< Button-2> bind), the output is:

Before my_menu popup

my_menu is visible on the screen. Then, when the user clicks out of the focus of that menu, the my_menu disappears you get the following output:

After my_menu popup
Before my_menu2 popup
After my_menu2 popup

The submenu appears on the screen but due to clicking out, the new focus is on the root and the submenu disappears in less than a second.

  • Related