Pregunta

I have an application containing many different items in a QGraphisScene. These items would be rectangles, ellipses, pixmaps, or anything that inherits from QGraphicsItem. The user can move around these items. (each of the QGraphicsItem::ItemIsMovable flag is set).

The application needs to get an event (a callback, a signal or whatever) to get the new position.

How can I overload the itemChanged() method for all of these possible items in one go?. I'd like do avoid subclassing each of my possible items (i.e. doing a derived class for QGraphicsEllipseItem, and onother for QGraphicsPixmapItem and a subclass for any future items...)?

I would like to be able to tell: Each time a QGraphicsItem (or anything derived from it) changes, call my function:

 my_item_changed(QGraphicItem* the_change_item,...).

And then being able to add different item types without having to worry about that any longer...

Any hint?

¿Fue útil?

Solución

You can install an event filter on the QGraphicsItems. In particular, you'll want to use this function: -

void QGraphicsItem::installSceneEventFilter(QGraphicsItem * filterItem);

As the Qt documentation states, here's an example of its usage: -

QGraphicsScene scene;
QGraphicsEllipseItem *ellipse = scene.addEllipse(QRectF(-10, -10, 20, 20));
QGraphicsLineItem *line = scene.addLine(QLineF(-10, -10, 20, 20));

line->installSceneEventFilter(ellipse);
// line's events are filtered by ellipse's sceneEventFilter() function.

ellipse->installSceneEventFilter(line);
// ellipse's events are filtered by line's sceneEventFilter() function.

Based on this, create a class, derived from QGraphicsItem, which can receive the events first. For each item you add to the scene, call the installSceneEventFilter: -

mySceneEventItem.installSceneEventFilter(pGraphicsItem);

Next, your eventFilter object overrides the function: -

bool QGraphicsItem::sceneEventFilter(QGraphicsItem * watched, QEvent * event)
{
    if(event->type() == QEvent::GraphicsSceneMove)
    {
        emit my_item_changed(watched); // signal that the item was moved
    }

    return false; // pass the event to the original target item
}

This allows you to check events and handle those that you're interested in. If you return false from sceneEventFilter, the event will be passed onto the original object, after you've dealt with it; returning true will block the event from being passed on.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top