Time for action – Event handling in a custom item

Items, like widgets, can receive events in virtual functions. If you click on a scene (to be precise, you click on a view that propagates the event to the scene), the scene receives the mouse press event, and it then becomes the scene's responsibility to determine which item was meant by the click.

Let's override the SineItem::mousePressEvent function that is called when the user presses a mouse button inside the item:

void SineItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->button() & Qt::LeftButton) {
        float x = event->pos().x();
        QPointF point(x, sin(x));
        static const float r = 0.3;
        QGraphicsEllipseItem *ellipse =
                new QGraphicsEllipseItem(-r, -r, 2 * r, 2 * r, this);
        ellipse->setPen(Qt::NoPen);
        ellipse->setBrush(QBrush(Qt::red));
        ellipse->setPos(point);
        event->accept();
    } else {
        event->ignore();
    }
}

When a mouse press event occurs, this function is called and the passed event object contains information about the event. In our case, we check whether the left mouse button was pressed and use the event->pos() function that returns coordinates of the clicked point in the item's coordinate system. In this example, we ignored the y coordinate and used the x coordinate to find the corresponding point on our graph. Then, we simply created a child circle item that shows that point. We accept the event if we did understand the action performed and ignore it if we don't know what it means so that it can be passed to another item. You can run the application and click on the graph to see these circles. Note that when you click outside of the graph's bounding rect, the scene doesn't dispatch the event to our item, and its mousePressEvent() function is not called.

The event object also contains the button() function that returns the button that was pressed, and the scenePos() function that returns the clicked point in the scene's coordinate system. The scene's responsibility for delivering events does not only apply to mouse events, but also to key events and all other sorts of events.