用鼠标将QGraphicsItem (boundingRect())调整为QGraphicsScene大小

时间:2023-01-31 23:17:07

I would like to resize the boundingRect() of my QGraphicsItem using the mouse.

我想使用鼠标调整QGraphicsItem的boundingRect()的大小。

To build this I found this topic. So I managed to make it work for the right, the bottomright and the bottom of my boundingRect() following the idea of this the topic.

为此,我找到了这个主题。因此,我设法使它适用于右边,右下角和我的boundingRect()的底部。

But since the position of my item is defined with the top left of the boundingRect() it is more complicated to modify the size of my item moving the edges linked to this position.

但是由于我的项目的位置是由boundingRect()的左上角定义的,因此修改项目的大小(移动与该位置相关联的边)会更加复杂。

I tried with the top left but the bottom right is also moving. I would like to have the bottom right fixed to only change the size and not the whole position.

我试过左上方,右下方也在移动。我想把右下角固定,只改变尺寸而不是整个位置。

Here is a part of my code:

以下是我的部分代码:

void Myclass::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 
{
    if(_resizemode) //if bottom selected
    {
        prepareGeometryChange();
        _h = event->pos().y();
    }

    if(_resizemode2) //if bottom right selected
    {
        prepareGeometryChange();
        _h = event->pos().y();
        _w = event->pos().x();

    }

    if(_resizemode3) //if right selected
    {
        prepareGeometryChange();
        _w = event->pos().x();
    }

    if(_resizemode4) //if top left selected HERE IS MY ISSUE
    {
        prepareGeometryChange();
        setPos(pos().x()+ event->pos().x(), pos().y() + event->pos().y());
        _h = _h - event->pos().y();
        _w = _w - event->pos().x();

    }

    if(!_resizemode&&!_resizemode2&&!_resizemode3&&!_resizemode4)
    {
    update();
    QGraphicsItem::mouseMoveEvent(event);
    }
}

_h and _w or the height and the width implemented here:

_h和_w或这里实现的高度和宽度:

QRectF Aabb::boundingRect() const
{
    return QRectF( 0, 0, _w, _h);
}

Does someone know how to resize a QGraphicsItem selecting with the mouse each corners of the boundingRect() please?

有人知道如何调整QGraphicsItem用鼠标选择boundingRect()的每个角落吗?

2 个解决方案

#1


1  

the position of my item is defined with the top left of the boundingRect()

我的项目的位置是在boundingRect()的左上角定义的

In my opinion, the easiest way is to change this so that the position is defined by the centre of the item. In order to do this, define the original bounding rect as top left (-w/2, -h/2) and bottom right (w/2,h/2) or if you're returning in the boundingRect function QRectF(-w/2, -h/2, w, h) for (x,y,w,h).

在我看来,最简单的方法是改变这一点,使位置由项目的中心来确定。为了做到这一点,将原始的边界矩形定义为左上角(-w/2, -h/2)和右下角(w/2,h/2),或者如果返回boundingRect函数QRectF(-w/2, -h/2, w,h)表示(x,y,w,h)。

Then, create child 'tool' items at the corners, which define the area which you can click and drag the corners of the original item. You may want these just to appear if the item is selected.

然后,在角落中创建子“工具”项,它定义您可以单击并拖动原始项的角的区域。如果选择了该项目,您可能希望这些内容仅仅显示出来。

In the moveEvent of the child item, update the bounding rect of the main item so that it moves with the child. When the mouse is released, re-calculate the boundingRect of the main item, so that its centre is still at (0,0).

在子项的moveEvent中,更新主项的边框rect,使其与子项一起移动。当释放鼠标时,重新计算主项的boundingRect,使其中心仍然为(0,0)。

This can be done quite easily if you map the top left and bottom right of the boundingRect and convert them to scene-coordinates, then using the width and height, re-set the item's local coordinates back so that it maintains (-w/2, -h/2, w, h);

如果将boundingRect的左上角和右下角映射到场景坐标,然后使用宽度和高度,重新设置项目的本地坐标,使其保持(-w/2, -h/2, w, h),这很容易实现;

#2


1  

I solved my problem. Here is what I have done so far for the mousePressEvent (defining the original boundingRect function like QRectF(-w/2, -h/2, w, h) ):

我解决了我的问题。下面是我到目前为止为mousePressEvent所做的(定义原始的boundingRect函数,如QRectF(-w/2, -h/2, w, h)):

void Myclass::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if(isSelected())
    {

    qDebug()<<"isseldeted";
    qreal adjust = 8;
    if((event->pos().x() > boundingRect().left() + adjust) && (event->pos().x() < boundingRect().right() - adjust) && (event->pos().y() < boundingRect().bottom() + adjust) && (event->pos().y() > boundingRect().bottom() - adjust) )
    {
        _adj = event->pos().y();
        _resizemode = true;
        qDebug()<<"bottom";
    }
    if((event->pos().x() > boundingRect().right() - adjust) && (event->pos().x() < boundingRect().right() + adjust) && (event->pos().y() < boundingRect().bottom() + adjust) && (event->pos().y() > boundingRect().bottom() - adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode2 = true;
        qDebug()<<"bottom right";

    }

    if((event->pos().x() > boundingRect().right() - adjust) && (event->pos().x() < boundingRect().right() + adjust) && (event->pos().y() < boundingRect().bottom() - adjust) && (event->pos().y() > boundingRect().top() + adjust))
    {
        _adj2 = event->pos().x();
        _resizemode3 = true;
        qDebug()<<"right";

    }

    if((event->pos().x() > boundingRect().left() - adjust) && (event->pos().x() < boundingRect().left() + adjust) && (event->pos().y() > boundingRect().top() - adjust) && (event->pos().y() < boundingRect().top() + adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode4 = true;
        qDebug()<<"top left";

    }

    if((event->pos().x() > boundingRect().left() - adjust) && (event->pos().x() < boundingRect().left() + adjust) && (event->pos().y() < boundingRect().bottom() - adjust) && (event->pos().y() > boundingRect().top() + adjust))
    {
        _adj2 = event->pos().x();
        _resizemode5 = true;
        qDebug()<<"left";

    }

    if((event->pos().x() > boundingRect().left() - adjust) && (event->pos().x() < boundingRect().left() + adjust) && (event->pos().y() < boundingRect().bottom() + adjust) && (event->pos().y() > boundingRect().bottom() - adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode6 = true;
        qDebug()<<"bottom left";

    }

    if((event->pos().x() > boundingRect().left() + adjust) && (event->pos().x() < boundingRect().right() - adjust) && (event->pos().y() < boundingRect().top() + adjust) && (event->pos().y() > boundingRect().top() - adjust))
    {
        _adj = event->pos().y();
        _resizemode7 = true;
        qDebug()<<"top";

    }

    if((event->pos().x() < boundingRect().right() + adjust) && (event->pos().x() > boundingRect().right() - adjust) && (event->pos().y() < boundingRect().top() + adjust) && (event->pos().y() > boundingRect().top() - adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode8 = true;
        qDebug()<<"top right";

    }
    }
update();
QGraphicsItem::mousePressEvent(event);
}

and for the mouseReleaseEvent:

和mouseReleaseEvent:

void Myclass::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if(_resizemode)
{
    prepareGeometryChange();
    _h += event->pos().y() - _adj; //good
    setPos(pos().x(), pos().y() + (event->pos().y() - _adj)/2 );//good

    _resizemode = false;
}

if(_resizemode2)
{
    _h += event->pos().y() - _adj; //good
    _w += event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2 );//good

    _resizemode2 = false;
}

if(_resizemode3)
{
    _w += event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y());//good

    _resizemode3 = false;
}

if(_resizemode4)
{
    _h -= event->pos().y() - _adj; //good
    _w -= event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2 );//good

    _resizemode4 = false;
}

if(_resizemode5)
{
    _w -= event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y());//good

    _resizemode5 = false;
}

if(_resizemode6)
{
    _h += event->pos().y() - _adj;
    _w -= event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2);//good

    _resizemode6= false;
}

if(_resizemode7)
{
    _h -= event->pos().y() - _adj;
    setPos(pos().x(), pos().y() + (event->pos().y() - _adj)/2);//good

    _resizemode7= false;
}

if(_resizemode8)
{
    _h -= event->pos().y() - _adj;
    _w += event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2);//good

    _resizemode8= false;
}

update();
QGraphicsItem::mouseReleaseEvent(event);
}

The mouseMoveEvent also need to be implemented:

穆萨维事件也需要实施:

void Aabb::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{   if(!_resizemode&&!_resizemode2&&!_resizemode3&&!_resizemode4&&!_resizemode5&&!_resizemode6&&!_resizemode7&&!_resizemode8)
    {
    update();
    QGraphicsItem::mouseMoveEvent(event);
    }
}

The problem is that we don't see the resizing in movement: we see the resized item when we release the mouse.

问题是我们没有看到移动的大小:当我们释放鼠标时,我们看到了大小调整的项。

Sometimes the item is not perfectly repositioned I don't know why.

有时我不知道为什么这件物品没有完美的重新定位。

So this is working but I believed it can be improved.

这是可行的,但我相信它可以改进。

#1


1  

the position of my item is defined with the top left of the boundingRect()

我的项目的位置是在boundingRect()的左上角定义的

In my opinion, the easiest way is to change this so that the position is defined by the centre of the item. In order to do this, define the original bounding rect as top left (-w/2, -h/2) and bottom right (w/2,h/2) or if you're returning in the boundingRect function QRectF(-w/2, -h/2, w, h) for (x,y,w,h).

在我看来,最简单的方法是改变这一点,使位置由项目的中心来确定。为了做到这一点,将原始的边界矩形定义为左上角(-w/2, -h/2)和右下角(w/2,h/2),或者如果返回boundingRect函数QRectF(-w/2, -h/2, w,h)表示(x,y,w,h)。

Then, create child 'tool' items at the corners, which define the area which you can click and drag the corners of the original item. You may want these just to appear if the item is selected.

然后,在角落中创建子“工具”项,它定义您可以单击并拖动原始项的角的区域。如果选择了该项目,您可能希望这些内容仅仅显示出来。

In the moveEvent of the child item, update the bounding rect of the main item so that it moves with the child. When the mouse is released, re-calculate the boundingRect of the main item, so that its centre is still at (0,0).

在子项的moveEvent中,更新主项的边框rect,使其与子项一起移动。当释放鼠标时,重新计算主项的boundingRect,使其中心仍然为(0,0)。

This can be done quite easily if you map the top left and bottom right of the boundingRect and convert them to scene-coordinates, then using the width and height, re-set the item's local coordinates back so that it maintains (-w/2, -h/2, w, h);

如果将boundingRect的左上角和右下角映射到场景坐标,然后使用宽度和高度,重新设置项目的本地坐标,使其保持(-w/2, -h/2, w, h),这很容易实现;

#2


1  

I solved my problem. Here is what I have done so far for the mousePressEvent (defining the original boundingRect function like QRectF(-w/2, -h/2, w, h) ):

我解决了我的问题。下面是我到目前为止为mousePressEvent所做的(定义原始的boundingRect函数,如QRectF(-w/2, -h/2, w, h)):

void Myclass::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if(isSelected())
    {

    qDebug()<<"isseldeted";
    qreal adjust = 8;
    if((event->pos().x() > boundingRect().left() + adjust) && (event->pos().x() < boundingRect().right() - adjust) && (event->pos().y() < boundingRect().bottom() + adjust) && (event->pos().y() > boundingRect().bottom() - adjust) )
    {
        _adj = event->pos().y();
        _resizemode = true;
        qDebug()<<"bottom";
    }
    if((event->pos().x() > boundingRect().right() - adjust) && (event->pos().x() < boundingRect().right() + adjust) && (event->pos().y() < boundingRect().bottom() + adjust) && (event->pos().y() > boundingRect().bottom() - adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode2 = true;
        qDebug()<<"bottom right";

    }

    if((event->pos().x() > boundingRect().right() - adjust) && (event->pos().x() < boundingRect().right() + adjust) && (event->pos().y() < boundingRect().bottom() - adjust) && (event->pos().y() > boundingRect().top() + adjust))
    {
        _adj2 = event->pos().x();
        _resizemode3 = true;
        qDebug()<<"right";

    }

    if((event->pos().x() > boundingRect().left() - adjust) && (event->pos().x() < boundingRect().left() + adjust) && (event->pos().y() > boundingRect().top() - adjust) && (event->pos().y() < boundingRect().top() + adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode4 = true;
        qDebug()<<"top left";

    }

    if((event->pos().x() > boundingRect().left() - adjust) && (event->pos().x() < boundingRect().left() + adjust) && (event->pos().y() < boundingRect().bottom() - adjust) && (event->pos().y() > boundingRect().top() + adjust))
    {
        _adj2 = event->pos().x();
        _resizemode5 = true;
        qDebug()<<"left";

    }

    if((event->pos().x() > boundingRect().left() - adjust) && (event->pos().x() < boundingRect().left() + adjust) && (event->pos().y() < boundingRect().bottom() + adjust) && (event->pos().y() > boundingRect().bottom() - adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode6 = true;
        qDebug()<<"bottom left";

    }

    if((event->pos().x() > boundingRect().left() + adjust) && (event->pos().x() < boundingRect().right() - adjust) && (event->pos().y() < boundingRect().top() + adjust) && (event->pos().y() > boundingRect().top() - adjust))
    {
        _adj = event->pos().y();
        _resizemode7 = true;
        qDebug()<<"top";

    }

    if((event->pos().x() < boundingRect().right() + adjust) && (event->pos().x() > boundingRect().right() - adjust) && (event->pos().y() < boundingRect().top() + adjust) && (event->pos().y() > boundingRect().top() - adjust))
    {
        _adj = event->pos().y();
        _adj2 = event->pos().x();
        _resizemode8 = true;
        qDebug()<<"top right";

    }
    }
update();
QGraphicsItem::mousePressEvent(event);
}

and for the mouseReleaseEvent:

和mouseReleaseEvent:

void Myclass::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if(_resizemode)
{
    prepareGeometryChange();
    _h += event->pos().y() - _adj; //good
    setPos(pos().x(), pos().y() + (event->pos().y() - _adj)/2 );//good

    _resizemode = false;
}

if(_resizemode2)
{
    _h += event->pos().y() - _adj; //good
    _w += event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2 );//good

    _resizemode2 = false;
}

if(_resizemode3)
{
    _w += event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y());//good

    _resizemode3 = false;
}

if(_resizemode4)
{
    _h -= event->pos().y() - _adj; //good
    _w -= event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2 );//good

    _resizemode4 = false;
}

if(_resizemode5)
{
    _w -= event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y());//good

    _resizemode5 = false;
}

if(_resizemode6)
{
    _h += event->pos().y() - _adj;
    _w -= event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2);//good

    _resizemode6= false;
}

if(_resizemode7)
{
    _h -= event->pos().y() - _adj;
    setPos(pos().x(), pos().y() + (event->pos().y() - _adj)/2);//good

    _resizemode7= false;
}

if(_resizemode8)
{
    _h -= event->pos().y() - _adj;
    _w += event->pos().x() - _adj2;
    setPos(pos().x() + (event->pos().x() - _adj2)/2, pos().y() + (event->pos().y() - _adj)/2);//good

    _resizemode8= false;
}

update();
QGraphicsItem::mouseReleaseEvent(event);
}

The mouseMoveEvent also need to be implemented:

穆萨维事件也需要实施:

void Aabb::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{   if(!_resizemode&&!_resizemode2&&!_resizemode3&&!_resizemode4&&!_resizemode5&&!_resizemode6&&!_resizemode7&&!_resizemode8)
    {
    update();
    QGraphicsItem::mouseMoveEvent(event);
    }
}

The problem is that we don't see the resizing in movement: we see the resized item when we release the mouse.

问题是我们没有看到移动的大小:当我们释放鼠标时,我们看到了大小调整的项。

Sometimes the item is not perfectly repositioned I don't know why.

有时我不知道为什么这件物品没有完美的重新定位。

So this is working but I believed it can be improved.

这是可行的,但我相信它可以改进。