Prevent QGraphicsItem from moving outside of QGraphicsScene

前端 未结 3 1515
孤城傲影
孤城傲影 2021-02-07 18:20

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

相关标签:
3条回答
  • 2021-02-07 18:37

    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());
        }
    }
    
    0 讨论(0)
  • 2021-02-07 18:49

    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

    0 讨论(0)
  • 2021-02-07 18:50

    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);
    }
    
    0 讨论(0)
提交回复
热议问题