Search code examples
qtmouseeventqgraphicsitemqgraphicsscene

How do you change the position of the boundingRect() of a QGraphicsItem on a QGraphicsScene?


I have set the boundingRect() of my QGraphicsItem to a certain coordinate on the scene. How can I change the coordinates based on the QGraphicsItem::mouseMoveEvent?


Below is the code I have written. But this code only sets the position of the shape I drew within the boundingRect() to a coordinate inside the boundingRect(). What I want to be able to do is move the entire QGraphicsItem to a set coordinate.

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

    if (y()>=394 && y()<425) //if in the range between 425 and 394 I want it to move to 440.
    {
        setPos(440, y());
    }
    else if ... //Other ranges such as that in the first if statement
    {
        ... //another y coordinate
    }
    else //If the item is not in any of the previous ranges it's y coordinate is set to 0
    {
        setPos(0,y()); //I had expected the item to go to y = 0 on the scene not the boundingRect()
    }

}

The scene is 880 by 860 and the boundingRect() is set like this:

QRectF QGraphicsItem::boundingRect() const
{
    return QRectF(780,425,60,30);
}

Solution

  • The bounding rect of an item defines the item in its local coordinates, whereas setting its position in the scene is using scene coordinates.

    For example, let's create a skeleton Square class, derived from QGraphicsItem

    class Square : public QGraphicsItem
    {
        Q_OBJECT
    public:
    
        Square(int size)
            : QGraphicsItem(NULL) // we could parent, but this may confuse at first
        {
            m_boundingRect = QRectF(0, 0, size, size);
        }
    
        QRectF boundingRect() const
        {
            return m_boundingRect;
        }
    
    private:
        QRectF m_boundingRect;
    };
    

    We can create a square with width and height of 10

    Square* square = new Square(10);
    

    If the item is added to a QGraphicsScene, it will appear at the top-left of the scene (0, 0);

    pScene->addItem(square); // assuming the Scene has been instantiated.
    

    Now we can move the square in the scene...

    square->setPos(100, 100);
    

    The square will move, but its width and height are still 10 units. If the bounding rect of the square is changed, then the rect itself changes, but its position in the scene is still the same. Let's resize the square...

    void Square::resize(int size)
    {
        m_boundingRect = QRectF(0, 0, size, size);
    }
    
    square->resize(100);
    

    The square now has width and height of 100, but its position is the same and we can can move the square separately from its defined bounding rect

    square->setPos(200, 200);
    

    What I want to be able to do is move the entire QGraphicsItem to a set coordinate.

    So, hopefully this has explained that the bounding rect is the internal (local coordinate) representation of the item, and to move the item, just call setPos, which will move the item relative to any parent, or if no parent exists, it will move it relative to the scene.