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?
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).
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).