Search code examples
qtqgraphicsviewqgraphicsitemqmouseevent

Can I get mouse events in a QGraphicsItem?


I have subclassed QGraphicsRectItem, and it's not receiving any mouse events. I've seen other questions similar to this say I need to enable mouse tracking, but setMouseTracking is in QWidget, and QGraphicsItem does not appear to be a QWidget.

I've implemented paint, and that's working. In my subclassed QGraphicsView I am getting mouse events.

The docs seem to think I should just override the mousePressEvent function (for example) and I should start getting the events. Whether I forward the mousePressEvent to the superclass of my QGraphicsView or not doesn't seem to make any difference.


Solution

  • In your subclassed QGraphicsView, you need to call the default implementations of overridden mouse event methods if you want them to propagate down to the items. For example:

    CustomView::mousePressEvent(QMouseEvent *event)
    {
        // handle the event as you like
    
        QGraphicsView::mousePressEvent(event); // then call default implementation
    }
    

    If you want to accept hover events, you need to call QGraphicsItem::setAcceptHoverEvents(true);. Otherwise you do not need to enable any particular mouse tracking.

    EDIT: Here is a full working example:

    #include <QtGui>
    
    class CustomView : public QGraphicsView
    {
    protected:
        void mousePressEvent(QMouseEvent *event)
        {
            qDebug() << "Custom view clicked.";
            QGraphicsView::mousePressEvent(event);
        }
    };
    
    class CustomItem : public QGraphicsRectItem
    {
    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event)
        {
            qDebug() << "Custom item clicked.";
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        CustomItem item;
        item.setRect(20, 20, 60, 60);
    
        QGraphicsScene scene(0, 0, 100, 100);
        scene.addItem(&item);
    
        CustomView view;
        view.setScene(&scene);
        view.show();
        return a.exec();
    }