Search code examples
qtqgraphicssceneqgraphicsitemqt6qgraphicsitemgroup

How to propagate QGraphicsItemGroup mouse events to child elements?


Is it possible to propagate QGraphicsItemGroup mouse events to child added items?

setHandlesChildEvents(false) is deprecated, and I don't want to use it.

I tried this, but it didn't work:

class MoveItemBase : public QObject, public QGraphicsItem;

bool sceneEvent(QEvent* event) override
{
    if (event->type() == QEvent::GraphicsSceneMouseDoubleClick) {
        propagateSceneEvent(event);
        return true;
    }

    return QGraphicsItemGroup::sceneEvent(event);
}

void propagateSceneEvent(QEvent* event)
{
    for (QGraphicsItem* child : childItems()) {
        MoveItemBase* widget = static_cast<MoveItemBase*>(child);  
        QCoreApplication::sendEvent(widget, event);
    }
}

Solution

  • As far as I know and found, there is no direct alternative to setHandlesChildEvents.

    I did however find a workaround in this thread on Qt Center Forum: setHandlesChildEvents() obsolete?, where it was suggested to use QGraphicsItem::installSceneEventFilter, which says:

    Installs an event filter for this item on filterItem, causing all events for this item to first pass through filterItem's sceneEventFilter() function.

    ...

    An item can only filter events for other items in the same scene.

    Based on these findings, I made a generic example to implement that:

    #include <QApplication>
    #include <QGraphicsView>
    #include <QGraphicsItem>
    
    //class of the item used as an event filter for other graphic items
    class FilterItem :  public QGraphicsLineItem
    {
    public:
        FilterItem (QGraphicsItem *parent = nullptr)
        {}
    
    protected:
        bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override
        {
            if(event->type() == QEvent::GraphicsSceneMouseDoubleClick)
            {
                qDebug()<<"Handling child graphics item event here";
                return true;
            }
    
            return QGraphicsItem::sceneEventFilter(watched,event);
        }
    };
    
    int main(int argc,char*argv[])
    {
        QApplication a(argc, argv);
    
        QGraphicsView v;
        QGraphicsScene scene;
        FilterItem *filterItem = new FilterItem;
        QGraphicsRectItem *targetItem = scene.addRect(QRect(10, 10, 50, 50));
    
        //the filter item has to be added to the same scene
        scene.addItem(filterItem);
        //install it on the targeted item
        targetItem->installSceneEventFilter(filterItem);
    
        v.setScene(&scene);
        v.show();
    
        return a.exec();
    }