From a45c125cee2c2af5df2af0e150cf6c85ffab9680 Mon Sep 17 00:00:00 2001 From: duanshengchao <519970194@qq.com> Date: Mon, 2 Sep 2024 17:56:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3item=E6=89=93=E7=BB=84?= =?UTF-8?q?=E4=B9=8B=E5=90=8E=EF=BC=8C=E5=AF=B9=E7=BB=84=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E2=80=98=E5=85=88=E6=97=8B=E8=BD=AC=E5=86=8D=E7=BC=A9=E6=94=BE?= =?UTF-8?q?=E2=80=99=E6=93=8D=E4=BD=9C=E7=9A=84=E6=BC=82=E7=A7=BB=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/drawingPanel.h | 4 ++ source/graphicsItem/graphicsItemGroup.cpp | 42 ++++++----- source/graphicsItem/graphicsRectItem.cpp | 6 +- source/operationCommand.cpp | 85 +++++++++++++++++++++-- 4 files changed, 115 insertions(+), 22 deletions(-) diff --git a/include/drawingPanel.h b/include/drawingPanel.h index fa65e79..c29b571 100644 --- a/include/drawingPanel.h +++ b/include/drawingPanel.h @@ -10,6 +10,7 @@ QT_END_NAMESPACE class DesignerView; class DesignerScene; +class GraphicsItemGroup; class DrawingPanel : public QWidget { @@ -26,6 +27,9 @@ public: void grahpicsViewZoomOut(); void grahpicsViewZoomFit(); + GraphicsItemGroup* createItemGroup(); + void destroyItemGroup(); + public slots: void onSignal_addGraphicsItem(GraphicsItemType&); diff --git a/source/graphicsItem/graphicsItemGroup.cpp b/source/graphicsItem/graphicsItemGroup.cpp index 92985a9..5b241ae 100644 --- a/source/graphicsItem/graphicsItemGroup.cpp +++ b/source/graphicsItem/graphicsItemGroup.cpp @@ -2,11 +2,13 @@ #include #include #include +#include GraphicsItemGroup::GraphicsItemGroup(QGraphicsItem *parent) : AbstractShapeType(parent) { m_boundingRect = QRectF(); + m_lastBoudingRect = QGraphicsItemGroup::boundingRect(); //初始化缩放操作用的handle m_vecHanle.reserve(H_left); @@ -52,9 +54,12 @@ void GraphicsItemGroup::paint(QPainter* painter, const QStyleOptionGraphicsItem* painter->drawRect(m_boundingRect_selected); //绘制变换原点 - // QPointF originPoint = transformOriginPoint(); - // painter->setBrush(Qt::red); - // painter->drawEllipse(originPoint, 4, 4); + QPointF originPoint = transformOriginPoint(); + //qDebug() << "originPoint:" << originPoint << " boundingRect:" << m_boundingRect; + painter->setBrush(Qt::red); + painter->drawEllipse(QPointF(0,0), 4, 4); + painter->setBrush(Qt::blue); + painter->drawEllipse(originPoint, 4, 4); } } @@ -90,23 +95,27 @@ void GraphicsItemGroup::updateCoordinate() //当执行了resie和editShape函数 m_dHeight = m_boundingRect.height(); } - QPointF pt1, pt2, delta; - pt1 = mapToScene(transformOriginPoint()); - pt2 = mapToScene(m_boundingRect.center()); - delta = pt1 - pt2; - + //因为group包含子item,boundingRect会根据子item自动计算生成,所以不再通过重设boundingRect(中心和原点重合)重合的方式,因为此种方式需要子item做各种同步计算 + //最简单的方式是,每次boundingRect发生变化(缩放)后重新设置变换中心,但是会出现漂移(因为item只存储旋转角度数据,每帧都根据角度进行重绘),具体见开发学习笔记,消除这个漂移即可 prepareGeometryChange(); - //boundingRect发生变化后原点偏离中心,将原点设为中心点,因为group内含有其它item,所以采用transform变换的方式 - //m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight); - setTransform(transform().translate(delta.x(), delta.y())); + //具体计算 + double dAngle = qDegreesToRadians(rotation()); + QPointF centerPt = m_boundingRect.center(); + QPointF originPt = transformOriginPoint(); + QPointF targetPt = QPointF(0, 0); + targetPt.setX(originPt.x() + qCos(dAngle)*(centerPt.x() - originPt.x()) - qSin(dAngle)*(centerPt.y() - originPt.y())); + targetPt.setY(originPt.y() + qSin(dAngle)*(centerPt.x() - originPt.x()) + qCos(dAngle)*(centerPt.y() - originPt.y())); + QPointF delta = targetPt - centerPt; + //m_boundingRect.adjust(delta.x(), delta.y(), delta.x(), delta.y()); setTransformOriginPoint(m_boundingRect.center()); - //更改原点后自身绘制会在新坐标系下进行,会有跳转,所以需要将item整体做对应的移动 - moveBy(-delta.x(), -delta.y()); + if(dAngle != 0) + moveBy(delta.x(), delta.y()); + + //QTimer::singleShot(2000,[&](){moveBy(-delta.x(), -delta.y());}); + updateHandles(); } - m_lastBoudingRect = m_boundingRect; - //调用该组内所有item(过滤handle)相关函数 foreach (QGraphicsItem *item, childItems()) { @@ -116,6 +125,7 @@ void GraphicsItemGroup::updateCoordinate() //当执行了resie和editShape函数 baseItem->updateCoordinate(); } } + m_lastBoudingRect = m_boundingRect; } void GraphicsItemGroup::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint) @@ -135,7 +145,7 @@ void GraphicsItemGroup::resize(int nHandle,double dSX, double dSY, const QPointF } QTransform trans; - //缩放是以图元原点(中心)位置为基准,所以每帧都先移动移动到想要的基准点,缩放之后再移回 + //缩放是以图元变换原点为基准,所以每帧都先移动移动到想要的基准点,缩放之后再移回 trans.translate(basePoint.x(), basePoint.y()); trans.scale(dSX, dSY); trans.translate(-basePoint.x(), -basePoint.y()); diff --git a/source/graphicsItem/graphicsRectItem.cpp b/source/graphicsItem/graphicsRectItem.cpp index 7636580..451db6c 100644 --- a/source/graphicsItem/graphicsRectItem.cpp +++ b/source/graphicsItem/graphicsRectItem.cpp @@ -74,15 +74,16 @@ void GraphicsRectItem::updateCoordinate() //当执行了resie和editShape函数 delta = pt1 - pt2; prepareGeometryChange(); - //boundingRect发生变化后原点偏离中心,将原点设为中心点 + //将boundingRect设置成中心点和原点(也是默认变换原点),这样三点重合,有助于简化计算 m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight); //setTransformOriginPoint(m_boundingRect.center()); //变换中心默认为item的(0,0)点,所以不执行这句话也没有问题 - //更改原点后自身绘制会在新坐标系下进行,会有跳转,所以需要将item整体做对应的移动 + //更新bouondingRect后重回会显示位置会有变化,需要做对应的移动 moveBy(-delta.x(), -delta.y()); updateHandles(); } m_lastBoudingRect = m_boundingRect; + //qDebug() << "itemPos:" << mapToParent(pos()); } void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) @@ -114,6 +115,7 @@ void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* //绘制变换原点 QPointF originPoint = transformOriginPoint(); + //qDebug() << "originPoint:" << originPoint; painter->setBrush(Qt::red); painter->drawEllipse(originPoint, 4, 4); } diff --git a/source/operationCommand.cpp b/source/operationCommand.cpp index a42e8e8..f45134e 100644 --- a/source/operationCommand.cpp +++ b/source/operationCommand.cpp @@ -1,4 +1,5 @@ #include "operationCommand.h" +#include "graphicsItem/graphicsItemGroup.h" #include AddItemCommand::AddItemCommand(QGraphicsItem* item, QGraphicsScene* scene, QUndoCommand* parent) @@ -39,8 +40,8 @@ void DeleteItemCommand::undo() { foreach(QGraphicsItem* item, m_listItem) { - QGraphicsItemGroup* group = dynamic_cast(item->parentItem()); - if(!group) + // QGraphicsItemGroup* group = dynamic_cast(item->parentItem()); + // if(!group) { m_pGraphicsScene->addItem(item); } @@ -52,8 +53,8 @@ void DeleteItemCommand::redo() { foreach(QGraphicsItem* item, m_listItem) { - QGraphicsItemGroup* group = dynamic_cast(item->parentItem()); - if(!group) + // QGraphicsItemGroup* group = dynamic_cast(item->parentItem()); + // if(!group) { m_pGraphicsScene->removeItem(item); //remove即可,不要delete,因为会影响撤回(undo)操作 } @@ -62,3 +63,79 @@ void DeleteItemCommand::redo() m_pGraphicsScene->update(); } +CreateItemGoupCommand::CreateItemGoupCommand(GraphicsItemGroup* group, QGraphicsScene* scene, QUndoCommand* parent) + : QUndoCommand(parent) +{ + m_pGroup = group; + m_pGraphicsScene = scene; + m_listItem = group->getItems(); +} +CreateItemGoupCommand::~CreateItemGoupCommand() +{ +} +void CreateItemGoupCommand::undo() +{ + m_pGroup->setSelected(false); + foreach (QGraphicsItem *item, m_listItem) + { + //item->setSelected(true); + m_pGroup->removeFromGroup(item); + AbstractShape *ab = qgraphicsitem_cast(item); + ab->updateCoordinate(); + ab->setSelected(true); + } + m_pGraphicsScene->removeItem(m_pGroup); + m_pGraphicsScene->update(); +} +void CreateItemGoupCommand::redo() +{ + if(!m_pGroup->scene()) //因为添加图元后同步创建一条该指令,平且在push进入stack的时候redo会被触发一次,因此这里加判断,防止重复操作 + { + foreach (QGraphicsItem *item, m_listItem) + { + item->setSelected(false); + m_pGroup->addToGroup(item); + } + m_pGraphicsScene->addItem(m_pGroup); + } + + m_pGroup->setSelected(true); + m_pGraphicsScene->update(); +} + +DestroyItemGoupCommand::DestroyItemGoupCommand(GraphicsItemGroup* group, QGraphicsScene* scene, QUndoCommand* parent) + : QUndoCommand(parent) +{ + m_pGroup = group; + m_pGraphicsScene = scene; + m_listItem = group->getItems(); +} +DestroyItemGoupCommand::~DestroyItemGoupCommand() +{ +} +void DestroyItemGoupCommand::undo() +{ + foreach (QGraphicsItem *item, m_listItem) + { + item->setSelected(false); + m_pGroup->addToGroup(item); + } + m_pGroup->setSelected(true); + m_pGraphicsScene->addItem(m_pGroup); + m_pGraphicsScene->update(); +} +void DestroyItemGoupCommand::redo() +{ + m_pGroup->setSelected(false); + foreach (QGraphicsItem *item, m_listItem) + { + //item->setSelected(true); + m_pGroup->removeFromGroup(item); + AbstractShape *ab = qgraphicsitem_cast(item); + ab->updateCoordinate(); + ab->setSelected(true); + } + m_pGraphicsScene->removeItem(m_pGroup); + m_pGraphicsScene->update(); +} +