Prevent QGraphicsItem from moving outside of QGraphicsScene

为君一笑 提交于 2020-01-01 08:33:55

问题


I have a scene which has fixed dimensions from (0;0) to (481;270):

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

Inside of it, I have a custom GraphicsItem and I can move it thanks to the flag ItemisMovable, but I would like it to stay within the Scene; I actually mean I don't want it to have coordinates neither under (0;0) nor over (481;270).

I tried several solutions like overriding QGraphicsItem::itemChange() or even QGraphicsItem::mouseMoveEvent() but I still cannot manage to reach what I want to do.

What is the suitable solution for my needs? Do I use QGraphicsItem::itemChange() badly?

Thanks in advance.


回答1:


You can override QGraphicsItem::mouseMoveEvent() like this:

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



回答2:


This code keeps your complete item in scene. Not only the upper left pixel of your item.

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



回答3:


Warning: The suggested solutions won't work for multiply selected items. The problem is, only one of the items receives a mouse move event in that case.

Actually, the Qt Documentation on QGraphicsItem provides an example which exactly solves the problem of limiting the movement of items to the scene 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);
}

Note I: You'd have to enable the QGraphicsItem::ItemSendsScenePositionChanges flag:

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

Note II: If you only want to react on finished movement, consider using the GraphicsItemChange flag ItemPositionHasChanged



来源:https://stackoverflow.com/questions/13102787/prevent-qgraphicsitem-from-moving-outside-of-qgraphicsscene

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!