Предотвратить на 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