Предотвратить на qgraphicsitem на qgraphicsscene двигаться за пределами

у меня есть сцена, которая имеет фиксированные размеры от (0;0) до (481;270):

scene->setSceneRect(0, 0, 481, 270);

внутри него, у меня есть заказ GraphicsItem и я могу переместить его благодаря флага ItemisMovable, но я хотел бы, чтобы он оставался внутри сцены; я на самом деле имею в виду, что я не хочу, чтобы он имел координаты ни под (0;0), ни над (481;270).

я попробовал несколько решений, таких как переопределение QGraphicsItem::itemChange() или даже QGraphicsItem::mouseMoveEvent() но я все еще не могу достичь того, что я хочу сделать.

что такое подходящее решение для моих нужд? Я использую QGraphicsItem::itemChange() плохо?

спасибо заранее.

3 ответов


можно переопределить QGraphicsItem::mouseMoveEvent() такой:

YourItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsItem::mouseMoveEvent(event); // move the item...

    // ...then check the bounds
    if (x() < 0)
        setPos(0, y());
    else if (x() > 481)
        setPos(481, y());

    if (y() < 0)
        setPos(x(), 0);
    else if (y() > 270)
        setPos(x(), 270);
}

этот код сохраняет ваш полный элемент в сцене. Не только верхний левый пиксель элемента.

void YourItem::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
{
    QGraphicsItem::mouseMoveEvent(event); 

    if (x() < 0)
    {
        setPos(0, y());
    }
    else if (x() + boundingRect().right() > scene()->width())
    {
        setPos(scene()->width() - boundingRect().width(), y());
    }

    if (y() < 0)
    {
        setPos(x(), 0);
    }
    else if ( y()+ boundingRect().bottom() > scene()->height())
    {
        setPos(x(), scene()->height() - boundingRect().height());
    }
}

предупреждение: предлагаемые решения не будут работать для умножения выбранных элементов. Проблема в том, что только один из элементов получает событие перемещения мыши в этом случае.

на самом деле документация Qt по QGraphicsItem предоставляет пример, который точно решает проблему ограничения перемещения элементов на сцену rect:

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

Примечание I: вы должны включить QGraphicsItem::ItemSendsScenePositionChanges флаг:

item->setFlags(QGraphicsItem::ItemIsMovable
               | QGraphicsItem::ItemIsSelectable
               | QGraphicsItem::ItemSendsScenePositionChanges);

Примечание. II: если вы хотите реагировать только на законченное движение, рассмотрите возможность использования GraphicsItemChange флаг ItemPositionHasChanged