Different Double Mouse Click Actions for Parent and Child QGraphicsObjects



  • Previously, I had the challenge of showing a different context menu for a QGraphicsScene and QGraphicsObject inside that QGraphicsScene, see https://forum.qt.io/topic/75009/different-context-menu-for-qgraphicsobject-in-qgraphicsscene

    Now, I have a similar issue but slightly different challenge: I have several QGraphicsObjects in this Scene. Some are painter over others due to being childern. Double clicking on the different QGraphicsObjects should invoke different actions (and double clicking somewhere on the QGraphicsScene where no QGraphicsObjects are should not invoke any action). I succeed to get the appropriate action invoked for the parent QGraphicsObjects but not for its child QGraphicsObjects. Any suggestions on how I can make the double click event somehow linked to the QGraphicsObject at the position of the mouse? I was unsuccessful in an attempt to use the same trick as suggested at the link above.


  • Moderators

    Either subclass the view and implement the mouseDoubleClickEvent or install event filter on it and listen for QEvent::MouseButtonDblClick. Then just see what's on the scene at that location and act accordingly:

    QGraphicsItem* item = view->itemAt(event->pos());
    if (item) {
       /* do something */
    }
    


  • I was trying to implement the first suggestion, but I don't succeed. I think I would need to cast the QMouseEvent for QGraphicsView::mouseDoubleClickEvent to a QGraphicsSceneMouseEvent for QGraphicsObject::mouseDoubleClickEvent. Here is my code:

    void ProcessView::mouseDoubleClickEvent(QMouseEvent *Event) {
    
        QPointF Position = Event->pos();
        QGraphicsItem* Item = itemAt(Position.x(), Position.y());
        if (Item != NULL) {
            ProcessDiagram* Process = dynamic_cast<ProcessDiagram *>(Item);
            if (Process) {
                ProcessDiagram::mouseDoubleClickEvent(Event);
                return;
            }
            PortDiagram* Terminal = dynamic_cast<PortDiagram *>(Item);
            if (Terminal) {
                PortDiagram::mouseDoubleClickEvent(Event);
                return;
            }
        }
    }
    

    Here ProcessView inherits from QGraphicsView and ProcessDiagram and PortDiagram both inherit from QGraphicsObject and have their own reimplementation of mouseDoubleClickEvent. This code does not work as QGraphicsObject::mouseDoubleClickEvent requires a QGraphicsSceneMouseEvent instead of a QMouseEvent...


  • Moderators

    You mixed it up. If you want to use the event on the item level then you don't need to override the view's method.
    I was thinking along the lines of

    void ProcessView::mouseDoubleClickEvent(QMouseEvent *Event) {
        QGraphicsItem* Item = itemAt(Event->pos());
        if (Item == someItem)
            someItem->doStuff();
        else if (item == someOtherItem)
           someOtherItem->DoOtherStuff();
    }
    

    but if you want to handle it on the item level then forget that and just implement it in the item:

    void ProcessDiagram::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* evt) {
       /* do stuff with evt*/
    }
    

    Note that for the item to receive this event it needs to be either selectable or movable, i.e.

    yourItem->setFlag(QGraphicsItem::ItemIsSelectable);
    


  • I want to handle the double clicks at the item level. Thanks to your suggestion of setting the selectable flag I got it to work ... almost: I now have to double double click when changing to a ProcessDiagram to a PortDiagram or vice verse to make the 'doStuff' / 'DoOtherStuff' to happen. I only need one double click if the type of item stays the same.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.