Important: Please read the Qt Code of Conduct -

[SOLVED] How to keep a context menu open

  • Hi everyone,

    I realize this may be a simple question for some of you, but I have searched far and wide (but maybe in the wrong places ...) for a solution for this:

    I want to enable a user to select several values in a context menu (right click/list of values pops up) - so I would like the menu to stay open once an item is selected. But default, the menus close on every selection. What is the best way to override this behavior?

    I am using Qt 4.7 from PySide (Python binding).



  • You can call setCheckable(true) on the actions, that makes the menu actions selectable. The usual way a menu works is that it closes once one entry is clicked, though. I don't see a direct solution for this.

    One option that comes into mind, is to use a QListView or QListWidget, that you show on a context menu request. That would stay open as long as you want and allows you to select multiple entries. You will have to take care of closing the view yourself - e.g. if someone clicks outside the view.

  • Dankeschoen!

    The setCheckable is nicer (more standard) than a custom icon that I was planning on using.

    I am worried about coding a new context menu from scratch (mine have to have a three level deep hierarchy) ... but there might be no way to avoid it!

    I was hoping that alternatively, maybe mouseEvents can be intercepted and filtered such that a click on an action will not call a slot to close the menu or some such things - but the mouse leaving the area of the menu will.


  • Intercepting the mouse events with an eventFilter() could be an option. I recommend studying the qmenu.cpp sources to not brick something :)

  • Here is the solution - works like a charm. I install the following eventFilter on all QMenus

    def eventFilter(self, obj, event):
    if event.type() in [QtCore.QEvent.MouseButtonRelease]:
    if isinstance(obj, QtGui.QMenu):
    if obj.activeAction():
    if not obj.activeAction().menu(): #if the selected action does not have a submenu
    #eat the event, but trigger the function
    return True
    return super(<my_class_name>, self).eventFilter(obj, event)

Log in to reply