Qt World Summit: Register Today!

Conflict between 2 context menus

  • Hi guys,
    I have a QGraphicsView observing a QGraphicsScene, and I have implemented a custom context menu on my QGraphicsView (by calling setContextMenuPolicy(Qt::CustomContextMenu)).

    Then I have added a simple QWidget to my scene, containing a QPushButton, and I want to implement another custom context menu on this button. But when I set the QPushButton context menu policy to Qt::CustomContextMenu and connect a slot to the customContextMenuRequested() signal, right clicking on the button opens the QGraphicsView context menu (i.e. the button context menu is covered by the QGraphicsView context menu).

    Is there any way to avoid this overlapping ?
    Thank you for your help.

  • Lifetime Qt Champion


    Can you provide a minimal sample code that shows that behaviour ?

    By the way:

    • What version of Qt are you using ?
    • On what platform ?

  • Qt Champions 2017

    Yes, Here is GraphicsView consumes the events and hence you are seeing the behaviour. Even though you are placing the widget, for the GraphicsView it is item only. Only option is to customise the scene class and write your own event handler.

  • @SGaist The code is quite big and it involves several classes, but I will try to provide a sample code asap. I am using Qt 4.8 on Windows .
    @dheerendra Which event handlers are you talking about ? I have tried an alternative solution which is using the underMouse method on my widget and disabling the GraphicsView context menu if the right click has been done on my widget. I don't know if this is a correct solution but at the moment I couldn't find any other way to do this.

  • Lifetime Qt Champion

    One possibility to think about: use an event filter. Then check for QContextMenuEvent, if the underlying element is your proxied widget, then forward the event to it, otherwise let it be handled by the scene.

  • @SGaist I went through all the docs of event filters (http://doc.qt.io/archives/qt-4.8/eventsandfilters.html and http://doc.qt.io/archives/qt-4.8/qobject.html#installEventFilter) but in the line
    monitoredObj->installEventFilter(filterObj); what is the monitored object, the QGraphicsScene or the QGraphicsView ? And should my widget be the filter object ?

  • Lifetime Qt Champion

    That depends on you, you can have a separate object that does the filtering.

    As for the scene or the view, the scene would make more sense it's it that contains all the items.

  • @SGaist I have installed an event filter on the scene, but it turns out that QContextMenuEvent is never called, instead QEvent::GraphicsSceneMousePress and QEvent::GraphicsSceneMouseReleased are called when I click on the widget. In addition, in the function bool FilterObject::eventFilter(QObject *object, QEvent *event), object is always my QGraphicsScene, thus from here I don't know how to forward events to my widget.
    However I managed to solve this with a workaround : I open the QGraphicsView ( QMenu::exec() ) only when myWidget->underMouse() returns false, and then I reimplement mousePressEvent and mouseReleaseEvent to deal with the right click.

  • Lifetime Qt Champion

    Do you mean in the slot connected to customContextMenuRequested ?

  • @SGaist Yes, I open the QGraphicsView context menu in the slot connected to customContextMenuRequested. I don't know if the use of underMouse() is convenient or not.

  • @DMIII
    I may be off-base here, but have a look at http://www.qtcentre.org/archive/index.php/t-65353.html:

    , the graphicsView context menu is beig shown, if I right-click on it, not one of the item.

    Look at the example code in QGraphicsView::itemAt(). You will need to implement something like that in your showContextMenu() slot - first check to see if there is an item at the QPoint. If there is, and it is one of your custom items, then you need to display its context menu (maybe send it a QGraphicsSceneContextMenuEvent). If there is nothing at the QPoint, then you display the QGraphicsView's context menu. The problem you are having is that the view's context menu handler is eating the right-clicks and your graphics items never see them.

    I have no idea, but don't you need to implement similar principle for the QWidget you are adding? In other words, it's your QGraphicsView job to recognise the right-click and forward it to the desired object.

  • @JonB Thank you for the link. I will try to implement this, but what is the difference between this and the solution I mentioned above ? I don't know if it is really important that the QGraphicsView recognise the right click.

Log in to reply