Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QGraphicsItem validating a position change

Tags:

qt

I have a custom QGraphicsItem implementation. I need to be able to limit where the item can be moved - i,e. restrict it to a certain area. When I checked the Qt documentation this is what it suggested:

QVariant Component::itemChange(GraphicsItemChange change, const QVariant &value)
 {
     if (change == ItemPositionChange && scene()) {
         // value is the new position.
         QPointF newPos = value.toPointF();
         QRectF rect = scene()->sceneRect();
         if (!rect.contains(newPos)) {
             // Keep the item inside the scene rect.
             newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
             newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
             return newPos;
         }
     }
     return QGraphicsItem::itemChange(change, value);
 }

So basically, check the position passed to itemChange, and if you don't like it, change it and return the new value.

Seems simple enough, except it doesn't actually work. When I checked the call stack I see that itemChange is being called from QGraphicsItem::setPos, but it doesn't even look at the return value. So there is no purpose to me returning a changed position, no one is looking at it. See code from QGraphicsItem.cpp

// Notify the item that the position is changing.
    const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos)));
    QPointF newPos = newPosVariant.toPointF();
    if (newPos == d_ptr->pos)
        return;

    // Update and repositition.
    d_ptr->setPosHelper(newPos);

    // Send post-notification.
    itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
    d_ptr->sendScenePosChange();

Any suggestions? I was hoping to avoid re-implementing the whole click and drag behavior myself using mouse-down mouse-move etc..., but I suppose I will have to if I can't find a better idea.

like image 718
Liz Avatar asked Dec 02 '10 00:12

Liz


1 Answers

I didn't actually try it but it looks to me it is checking the return position. The returned restricted position is used in the constructor of newPosVariant to converted to newPos. It's then used to set the position of the item if it's different from the current one.

like image 99
Stephen Chu Avatar answered Nov 15 '22 09:11

Stephen Chu