修复采用拖拽方式进行创建的item和缩放操作有轻微漂移的bug

This commit is contained in:
duanshengchao 2024-11-20 14:40:13 +08:00
parent 0f6de6317e
commit b234cdd3ca
8 changed files with 54 additions and 29 deletions

View File

@ -122,32 +122,40 @@ public:
virtual QPointF getSymmetricPointPos(int nHandle) //获取对称点的坐标位置,缩放的时候需要以对称点为锚点 virtual QPointF getSymmetricPointPos(int nHandle) //获取对称点的坐标位置,缩放的时候需要以对称点为锚点
{ {
QPointF pt; QPointF pt;
//编号从1开始因此下标需要-1 //handle的位置相对boundingRect会有一个向外的错位因此直接采用bounddingRect的相应位置会更精准
switch (nHandle) switch (nHandle)
{ {
case H_leftTop: case H_leftTop:
pt = m_vecHanle.at(H_rightBottom - 1)->pos(); //pt = m_vecHanle.at(H_rightBottom - 1)->pos();
pt = m_boundingRect.bottomRight();
break; break;
case H_top: case H_top:
pt = m_vecHanle.at(H_bottom - 1)->pos(); //pt = m_vecHanle.at(H_bottom - 1)->pos();
pt = QPointF(m_boundingRect.width() * 0.5, m_boundingRect.bottom());
break; break;
case H_rightTop: case H_rightTop:
pt = m_vecHanle.at(H_leftBottom - 1)->pos(); //pt = m_vecHanle.at(H_leftBottom - 1)->pos();
pt = m_boundingRect.bottomLeft();
break; break;
case H_right: case H_right:
pt = m_vecHanle.at(H_left - 1)->pos(); //pt = m_vecHanle.at(H_left - 1)->pos();
pt = QPointF(m_boundingRect.left(), m_boundingRect.height() * 0.5);
break; break;
case H_rightBottom: case H_rightBottom:
pt = m_vecHanle.at(H_leftTop - 1)->pos(); //pt = m_vecHanle.at(H_leftTop - 1)->pos();
pt = m_boundingRect.topLeft();
break; break;
case H_bottom: case H_bottom:
pt = m_vecHanle.at(H_top - 1)->pos(); //pt = m_vecHanle.at(H_top - 1)->pos();
pt = QPointF(m_boundingRect.width() * 0.5, m_boundingRect.top());
break; break;
case H_leftBottom: case H_leftBottom:
pt = m_vecHanle.at(H_rightTop - 1)->pos(); //pt = m_vecHanle.at(H_rightTop - 1)->pos();
pt = m_boundingRect.topRight();
break; break;
case H_left: case H_left:
pt = m_vecHanle.at(H_right - 1)->pos(); //pt = m_vecHanle.at(H_right - 1)->pos();
pt = QPointF(m_boundingRect.right(), m_boundingRect.height() * 0.5);
break; break;
default: default:
break; break;

View File

@ -20,7 +20,7 @@ public:
void rotateOperationCopy(const double&); void rotateOperationCopy(const double&);
void addItems(const QList<QGraphicsItem*>&); void addItems(const QList<QGraphicsItem*>&);
QList<QGraphicsItem*> getItems() {return m_listItem;} //QList<QGraphicsItem*> getItems() {return m_listItem;}
protected: protected:
virtual QPainterPath shape(); virtual QPainterPath shape();
@ -30,8 +30,9 @@ protected:
virtual void syncRotationDataFromParent(const double&); virtual void syncRotationDataFromParent(const double&);
private: private:
QRectF m_lastBoudingRect; //记录上一时刻的boundingRect QRectF m_lastBoudingRect; //记录上一时刻的boundingRect
QList<QGraphicsItem*> m_listItem; QPainterPath m_painterPath;
//QList<QGraphicsItem*> m_listItem;
}; };
#endif #endif

View File

@ -38,7 +38,7 @@ private:
CreatingMethod m_creatingMethod; CreatingMethod m_creatingMethod;
GraphicsItemType m_creatingItemType; GraphicsItemType m_creatingItemType;
GraphicsBaseItem* m_pCreatingItem; GraphicsBaseItem* m_pCreatingItem;
QPointF m_scalBasePoint; //QPointF m_scalBasePoint;
}; };
#endif #endif

View File

@ -183,6 +183,8 @@ void GraphicsItemGroup::resize(int nHandle,double dSX, double dSY, const QPointF
trans.translate(-basePoint.x(), -basePoint.y()); trans.translate(-basePoint.x(), -basePoint.y());
prepareGeometryChange(); prepareGeometryChange();
//如果直接将变换应用到item(setTransform(trans)),相当于把坐标进行拉伸,会有明显的拉伸感,所以应用到图形点上效果更好
//setTransform(trans);
m_boundingRect = trans.mapRect(m_lastBoudingRect); m_boundingRect = trans.mapRect(m_lastBoudingRect);
m_dWidth = m_boundingRect.width(); m_dWidth = m_boundingRect.width();
m_dHeight = m_boundingRect.height(); m_dHeight = m_boundingRect.height();
@ -194,7 +196,8 @@ void GraphicsItemGroup::resize(int nHandle,double dSX, double dSY, const QPointF
GraphicsBaseItem *baseItem = qgraphicsitem_cast<GraphicsBaseItem*>(item); GraphicsBaseItem *baseItem = qgraphicsitem_cast<GraphicsBaseItem*>(item);
if (baseItem && !qgraphicsitem_cast<ItemControlHandle*>(baseItem)) if (baseItem && !qgraphicsitem_cast<ItemControlHandle*>(baseItem))
{ {
baseItem->resize(nHandle, dSX, dSY, baseItem->mapFromParent(basePoint)); //qDebug() << "groupBounding: " << m_boundingRect << " itemBounding:" << baseItem->boundingRect();
baseItem->resize(nHandle, dSX, dSY, baseItem->mapFromParent(basePoint));
} }
} }
} }
@ -278,7 +281,7 @@ void GraphicsItemGroup::addItems(const QList<QGraphicsItem*>& items)
{ {
item->setSelected(false); item->setSelected(false);
addToGroup(item); addToGroup(item);
m_listItem.push_back(item); //m_listItem.push_back(item);
} }
updateCoordinate(); updateCoordinate();

View File

@ -51,8 +51,8 @@ void GraphicPolygonItem::updateCoordinate() //当执行了resie和editShape函
prepareGeometryChange(); prepareGeometryChange();
//更改图形绘制节点坐标,让图形中心和原点对齐 //更改图形绘制节点坐标,让图形中心和原点对齐
QPolygonF ptsOnScene = mapToScene(m_points); //所有操作都在scene坐标系下进行然后在还原至item坐标系否则会有跳转 QPolygonF ptsOnScene = mapToScene(m_points); //所有操作都在scene坐标系下进行然后在还原至item坐标系否则会有跳转
for(int i=0; i<m_points.count(); i++) for(int i=0; i<ptsOnScene.count(); i++)
ptsOnScene[i] += delta; //一定要在scene坐标系下执行操作不能直接m_points += delta;因为缩放以后item自身的内部坐标系也会同步缩放单位刻度和scene下的单位刻度不再一致,所以所有相关计算一定要在同一个坐标系下完成 ptsOnScene[i] += delta; //一定要在scene坐标系下执行操作不能直接m_points += delta;因为旋转以后item自身的内部坐标系和scene下的不再一致,所以所有相关计算一定要在同一个坐标系下完成
m_points = mapFromScene(ptsOnScene); m_points = mapFromScene(ptsOnScene);
m_boundingRect = m_points.boundingRect(); m_boundingRect = m_points.boundingRect();
//移动整体图形,消除节点坐标更后的绘制跳转 //移动整体图形,消除节点坐标更后的绘制跳转

View File

@ -123,6 +123,7 @@ void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*
void GraphicsRectItem::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint) void GraphicsRectItem::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint)
{ {
//qDebug() << basePoint;
switch (nHandle) switch (nHandle)
{ {
case H_left: case H_left:

View File

@ -68,7 +68,12 @@ CreateItemGoupCommand::CreateItemGoupCommand(GraphicsItemGroup* group, QGraphics
{ {
m_pGroup = group; m_pGroup = group;
m_pGraphicsScene = scene; m_pGraphicsScene = scene;
m_listItem = group->getItems(); foreach (QGraphicsItem *item, group->childItems())
{
if(!qgraphicsitem_cast<ItemControlHandle*>(item))
m_listItem.push_back(item);
}
//m_listItem = group->getItems();
} }
CreateItemGoupCommand::~CreateItemGoupCommand() CreateItemGoupCommand::~CreateItemGoupCommand()
{ {
@ -108,7 +113,12 @@ DestroyItemGoupCommand::DestroyItemGoupCommand(GraphicsItemGroup* group, QGraphi
{ {
m_pGroup = group; m_pGroup = group;
m_pGraphicsScene = scene; m_pGraphicsScene = scene;
m_listItem = group->getItems(); foreach (QGraphicsItem *item, group->childItems())
{
if(!qgraphicsitem_cast<ItemControlHandle*>(item))
m_listItem.push_back(item);
}
//m_listItem = group->getItems();
} }
DestroyItemGoupCommand::~DestroyItemGoupCommand() DestroyItemGoupCommand::~DestroyItemGoupCommand()
{ {
@ -120,8 +130,9 @@ void DestroyItemGoupCommand::undo()
item->setSelected(false); item->setSelected(false);
m_pGroup->addToGroup(item); m_pGroup->addToGroup(item);
} }
m_pGroup->setSelected(true);
m_pGraphicsScene->addItem(m_pGroup); m_pGraphicsScene->addItem(m_pGroup);
m_pGroup->setSelected(true);
m_pGraphicsScene->update(); m_pGraphicsScene->update();
} }
void DestroyItemGoupCommand::redo() void DestroyItemGoupCommand::redo()

View File

@ -10,7 +10,7 @@ CreatingSelector::CreatingSelector(QObject *parent)
m_type = ST_cerating; m_type = ST_cerating;
m_creatingMethod = CM_drag; m_creatingMethod = CM_drag;
m_pCreatingItem = nullptr; m_pCreatingItem = nullptr;
m_scalBasePoint = QPointF(); //m_scalBasePoint = QPointF();
} }
CreatingSelector::~CreatingSelector() CreatingSelector::~CreatingSelector()
{ {
@ -34,7 +34,7 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer
case GIT_rect: case GIT_rect:
{ {
m_creatingMethod = CM_drag; m_creatingMethod = CM_drag;
m_pCreatingItem = new GraphicsRectItem(QRect(1, 1, 1, 1)); m_pCreatingItem = new GraphicsRectItem(QRect(-2, -2, 4, 4));
} }
break; break;
case GIT_roundRect: case GIT_roundRect:
@ -86,22 +86,23 @@ void CreatingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerS
if (m_pCreatingItem && m_creatingMethod == CM_drag) if (m_pCreatingItem && m_creatingMethod == CM_drag)
{ {
if(m_scalBasePoint.isNull()) //基准点不能采用临时变量因为handle的坐标也在不断变化计算会出现问题 /*if(m_scalBasePoint.isNull()) //基准点不能采用临时变量因为handle的坐标也在不断变化计算会出现问题
{ {
m_scalBasePoint = m_pCreatingItem->getSymmetricPointPos(ms_nDragHandle); m_scalBasePoint = m_pCreatingItem->getSymmetricPointPos(ms_nDragHandle); qDebug() << m_scalBasePoint;
if(m_scalBasePoint.x() == 0) if(m_scalBasePoint.x() == 0)
m_scalBasePoint.setX(1); m_scalBasePoint.setX(1);
if(m_scalBasePoint.y() == 0) if(m_scalBasePoint.y() == 0)
m_scalBasePoint.setY(1); m_scalBasePoint.setY(1);
} }*/
QPointF scaleBasePoint = m_pCreatingItem->boundingRect().topLeft();
//计算缩放倍数 //计算缩放倍数
QPointF iniDelta = m_pCreatingItem->mapFromScene(ms_ptMouseDown) - m_scalBasePoint; QPointF iniDelta = m_pCreatingItem->mapFromScene(ms_ptMouseDown) - scaleBasePoint;
QPointF lastDelta = m_pCreatingItem->mapFromScene(ms_ptMouseLast) - m_scalBasePoint; QPointF lastDelta = m_pCreatingItem->mapFromScene(ms_ptMouseLast) - scaleBasePoint;
double sx = lastDelta.x() / iniDelta.x(); double sx = lastDelta.x() / iniDelta.x();
double sy = lastDelta.y() / iniDelta.y(); double sy = lastDelta.y() / iniDelta.y();
m_pCreatingItem->resize(ms_nDragHandle, sx, sy, m_scalBasePoint); m_pCreatingItem->resize(ms_nDragHandle, sx, sy, scaleBasePoint);
} }
else if (m_pCreatingItem && m_creatingMethod == CM_click) else if (m_pCreatingItem && m_creatingMethod == CM_click)
{ {
@ -130,7 +131,7 @@ void CreatingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Design
ms_nDragHandle = H_none; ms_nDragHandle = H_none;
m_pCreatingItem = nullptr; m_pCreatingItem = nullptr;
m_scalBasePoint = QPointF(); //m_scalBasePoint = QPointF();
setCursor(scene, Qt::ArrowCursor); setCursor(scene, Qt::ArrowCursor);
emit setWorkingSelector(ST_base); emit setWorkingSelector(ST_base);
} }