2

I think my question is similar to this post but in C++ and inside a QGraphicsItem.

I would like to fix the movable area of my object inside an other QGraphicsItem. I want my object to stay inside if I try to move it outside.

Maybe the idea will be to use setParentItem().

Does someone know how to restrict a movable area inside a QGraphicsItem please?

Community
  • 1
  • 1
Jeanstackamort
  • 309
  • 2
  • 4
  • 16

2 Answers2

5

Yes, you are correct. As in here you have to reimplement itemChange. From the qt documentation

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);
}

where scene() refers to the QGraphicsScene in which the item reside. If you don't use a QGraphicScene you must set a QRectF appropriately (maybe from the parent item geometry).

Community
  • 1
  • 1
Salvatore Avanzo
  • 2,656
  • 1
  • 21
  • 30
  • Thank you. I tried your code and this is blocking my `QRectF` from my movable `QGraphicsItem` at the left and at the top of my scene. I still need to block it at the right and at the bottom of my scene (probably tweaking the code using `boundingRect().bottomRight()`). I will try and let you know. – Jeanstackamort Mar 20 '14 at 10:32
  • 1
    Actually I don't know why your code is not working at the right and at the bottom of the scene for the top left corner... – Jeanstackamort Mar 20 '14 at 10:38
  • @user2886875 : it may depend on rect that you've used. You should debug/print your actual rect's coordinates. – Salvatore Avanzo Mar 20 '14 at 10:47
  • Yes I just noticed that my the right of my rect change if my object go further it. It is expandable. – Jeanstackamort Mar 20 '14 at 11:03
  • @user2886875 How did you implemented your parent boundingRect? Your QGraphicItem parent is a QGraphicItem also, right? – Salvatore Avanzo Mar 20 '14 at 11:35
  • Yes it is also a QGraphicsItem. So I used the boundingRect of this parent to set the QRectF of the scene like this: `_scene->setSceneRect(0,0,Item->boundingRect().right(),Item->boundingRect().bottom());` Now the `sceneRect()` is fixed! – Jeanstackamort Mar 20 '14 at 13:54
  • To restrict at bottom right corner I used a simple trick `rect = self.parentItem().boundingRect().adjusted(0, 0, -self.boundingRect().width(), -self.boundingRect().height())` (python code)(I used parents rect since I have used the setParentItem() method) – JacksonPro May 12 '21 at 06:53
3

I solved my problem!

For this I add to redefine how to set the position of my QGraphicsItem. My item is just define by the boundingRect() like this:

QRectF MyClass::boundingRect() const
{
return QRectF( -_w/2, -_h/2, _w, _h);
}

So I wanted this QRectF to stay inside the scene. The position of my item is define by the center of this QRectF. Using the code from the Qt documentation proposed by @Salvatore Avanzo here is my code:

QVariant Aabb::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.x() - _w/2, newPos.y() -     _h/2)||!rect.contains(newPos.x() - _w/2, newPos.y() + _h/2)||!rect.contains(newPos.x() + _w/2, newPos.y() + _h/2)||!rect.contains(newPos.x() + _w/2, newPos.y() - _h/2)) 
    {
        // Keep the item inside the scene rect.
        newPos.setX(qMin(rect.right() - _w/2, qMax(newPos.x() , rect.left() + _w/2)));
        newPos.setY(qMin(rect.bottom() - _h/2, qMax(newPos.y() , rect.top() + _h/2)));
        return newPos;
    }


}

return QGraphicsItem::itemChange(change, value);
}

Don't forget to set the QRectF of the scene (see comments in the question).

Jeanstackamort
  • 309
  • 2
  • 4
  • 16