Question

I'm new to Qt programming. So far I made a QGraphicsScene draw some rectangles (looks like a Chess Board) and then added an own QGraphicsItem to the scene. For this item I set the ItemIsMovable flag. Now I can move it but I would like to restrict the movement to the area where the Chess Board is.

Would I have to unset the flag and realize the movement manually or is there like an option or flag where I can specify the area it can be moved in ?

renderableObject::renderableObject(QObject */*parent*/)
{
    pressed = false;
    setFlag(ItemIsMovable);
}
Was it helpful?

Solution

You can reimplement the QGraphicsItem's itemChange() if you want to restrict movable area. Repositioning the item will cause itemChange to get called. You should note that ItemSendsGeometryChanges flag is needed to capture the change in position of QGraphicsItem.

class MyItem : public QGraphicsRectItem
{
public:
    MyItem(const QRectF & rect, QGraphicsItem * parent = 0);
protected:
    virtual QVariant    itemChange ( GraphicsItemChange change, const QVariant & value );
};


MyItem::MyItem(const QRectF & rect, QGraphicsItem * parent )
    :QGraphicsRectItem(rect,parent)
{
    setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges);
}

QVariant MyItem::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);
}

This will keep item moving limited to scene rect. You can define any arbitrary rect if you like.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top