Python3 Tkinter popup menu not closing automatically when clicking elsewhere

Question:

I’m running Python 3.3.3 (and right now I’m on Ubuntu but I also develop on Mac and Windows, which I haven’t yet tested). I have a Treeview object that responds to right click on items and shows a context menu depending on what you click… but I’ve noticed that if you right click somewhere else while the original menu is up, it just opens another one.

In fact, normal clicking doesn’t hide them either. Even when I close the window the menus still stay floating. The only way to get them to go away is to click one of the options.

The end result is this:
Context Menus EVERYWHERE

My code for the menu is as follows:

def rightclick_listitem(self, event):
    rowitem = self.sources.identify('item', event.x, event.y)

    if rowitem == '':
        print('Right clicked an empty space.')
        return
    # user right clicked something.
    self.sources.selection_set(rowitem)
    rcmenu = Menu(self.root, tearoff=0)
    plugin_disabled=self.sources.item(rowitem, 'values')[0] == 'Disabled'
    if plugin_disabled:
        rcmenu.add_command(label='Plugin is disabled...',
                           command=self.plugin_disabled_click)
    rcmenu.add_command(label='Plugin options',state='disabled' if plugin_disabled else 'active')
    rcmenu.add_command(label='Uninstall plugin')
    rcmenu.post(event.x_root, event.y_root)

The code that calls this code is located here:

    #RIGHTMOUSE is a variable that changes based on OS due to the way Mac OSX works
    #sources is the treeview object
    self.sources.bind(RIGHTMOUSE, self.rightclick_listitem)

I googled around and only got some people asking the same question with no answers. I’m still somewhat new to tkinter and python in general, and didn’t see anything about this. I bind other actions to the treeview as well.

If you need more sourcecode my project is here: https://github.com/Mgamerz/Fresh-Set-of-Images (freshsetofimages.py)

Any help is appreciated.

And the plugins required to make this appear: https://github.com/Mgamerz/fsoi_plugins

Asked By: Mgamerz

||

Answers:

Try calling the method tk_popup rather than post.

Also, your code has a memory leak, in that each time you right-click you’re creating a new menu but never destroying the old one. You only ever need to create one, and the reconfigure it before popping it up.

Answered By: Bryan Oakley

To close the popup menu when click elsewhere, you can add

rcmenu.bind("<FocusOut>",popupFocusOut)

and call unpost in popupFocusOut.

def popupFocusOut(self,event=None):
        rcmenu.unpost()
Answered By: Gavin
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.