解决item打组之后,对组进行‘先旋转再缩放’操作的漂移问题
This commit is contained in:
parent
a4b8556a47
commit
a45c125cee
|
|
@ -10,6 +10,7 @@ QT_END_NAMESPACE
|
||||||
|
|
||||||
class DesignerView;
|
class DesignerView;
|
||||||
class DesignerScene;
|
class DesignerScene;
|
||||||
|
class GraphicsItemGroup;
|
||||||
|
|
||||||
class DrawingPanel : public QWidget
|
class DrawingPanel : public QWidget
|
||||||
{
|
{
|
||||||
|
|
@ -26,6 +27,9 @@ public:
|
||||||
void grahpicsViewZoomOut();
|
void grahpicsViewZoomOut();
|
||||||
void grahpicsViewZoomFit();
|
void grahpicsViewZoomFit();
|
||||||
|
|
||||||
|
GraphicsItemGroup* createItemGroup();
|
||||||
|
void destroyItemGroup();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onSignal_addGraphicsItem(GraphicsItemType&);
|
void onSignal_addGraphicsItem(GraphicsItemType&);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
GraphicsItemGroup::GraphicsItemGroup(QGraphicsItem *parent)
|
GraphicsItemGroup::GraphicsItemGroup(QGraphicsItem *parent)
|
||||||
: AbstractShapeType<QGraphicsItemGroup>(parent)
|
: AbstractShapeType<QGraphicsItemGroup>(parent)
|
||||||
{
|
{
|
||||||
m_boundingRect = QRectF();
|
m_boundingRect = QRectF();
|
||||||
|
m_lastBoudingRect = QGraphicsItemGroup::boundingRect();
|
||||||
|
|
||||||
//初始化缩放操作用的handle
|
//初始化缩放操作用的handle
|
||||||
m_vecHanle.reserve(H_left);
|
m_vecHanle.reserve(H_left);
|
||||||
|
|
@ -52,9 +54,12 @@ void GraphicsItemGroup::paint(QPainter* painter, const QStyleOptionGraphicsItem*
|
||||||
painter->drawRect(m_boundingRect_selected);
|
painter->drawRect(m_boundingRect_selected);
|
||||||
|
|
||||||
//绘制变换原点
|
//绘制变换原点
|
||||||
// QPointF originPoint = transformOriginPoint();
|
QPointF originPoint = transformOriginPoint();
|
||||||
// painter->setBrush(Qt::red);
|
//qDebug() << "originPoint:" << originPoint << " boundingRect:" << m_boundingRect;
|
||||||
// painter->drawEllipse(originPoint, 4, 4);
|
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();
|
m_dHeight = m_boundingRect.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF pt1, pt2, delta;
|
//因为group包含子item,boundingRect会根据子item自动计算生成,所以不再通过重设boundingRect(中心和原点重合)重合的方式,因为此种方式需要子item做各种同步计算
|
||||||
pt1 = mapToScene(transformOriginPoint());
|
//最简单的方式是,每次boundingRect发生变化(缩放)后重新设置变换中心,但是会出现漂移(因为item只存储旋转角度数据,每帧都根据角度进行重绘),具体见开发学习笔记,消除这个漂移即可
|
||||||
pt2 = mapToScene(m_boundingRect.center());
|
|
||||||
delta = pt1 - pt2;
|
|
||||||
|
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
//boundingRect发生变化后原点偏离中心,将原点设为中心点,因为group内含有其它item,所以采用transform变换的方式
|
//具体计算
|
||||||
//m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight);
|
double dAngle = qDegreesToRadians(rotation());
|
||||||
setTransform(transform().translate(delta.x(), delta.y()));
|
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());
|
setTransformOriginPoint(m_boundingRect.center());
|
||||||
//更改原点后自身绘制会在新坐标系下进行,会有跳转,所以需要将item整体做对应的移动
|
if(dAngle != 0)
|
||||||
moveBy(-delta.x(), -delta.y());
|
moveBy(delta.x(), delta.y());
|
||||||
|
|
||||||
|
//QTimer::singleShot(2000,[&](){moveBy(-delta.x(), -delta.y());});
|
||||||
|
|
||||||
updateHandles();
|
updateHandles();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastBoudingRect = m_boundingRect;
|
|
||||||
|
|
||||||
//调用该组内所有item(过滤handle)相关函数
|
//调用该组内所有item(过滤handle)相关函数
|
||||||
foreach (QGraphicsItem *item, childItems())
|
foreach (QGraphicsItem *item, childItems())
|
||||||
{
|
{
|
||||||
|
|
@ -116,6 +125,7 @@ void GraphicsItemGroup::updateCoordinate() //当执行了resie和editShape函数
|
||||||
baseItem->updateCoordinate();
|
baseItem->updateCoordinate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_lastBoudingRect = m_boundingRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsItemGroup::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint)
|
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;
|
QTransform trans;
|
||||||
//缩放是以图元原点(中心)位置为基准,所以每帧都先移动移动到想要的基准点,缩放之后再移回
|
//缩放是以图元变换原点为基准,所以每帧都先移动移动到想要的基准点,缩放之后再移回
|
||||||
trans.translate(basePoint.x(), basePoint.y());
|
trans.translate(basePoint.x(), basePoint.y());
|
||||||
trans.scale(dSX, dSY);
|
trans.scale(dSX, dSY);
|
||||||
trans.translate(-basePoint.x(), -basePoint.y());
|
trans.translate(-basePoint.x(), -basePoint.y());
|
||||||
|
|
|
||||||
|
|
@ -74,15 +74,16 @@ void GraphicsRectItem::updateCoordinate() //当执行了resie和editShape函数
|
||||||
delta = pt1 - pt2;
|
delta = pt1 - pt2;
|
||||||
|
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
//boundingRect发生变化后原点偏离中心,将原点设为中心点
|
//将boundingRect设置成中心点和原点(也是默认变换原点),这样三点重合,有助于简化计算
|
||||||
m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight);
|
m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight);
|
||||||
//setTransformOriginPoint(m_boundingRect.center()); //变换中心默认为item的(0,0)点,所以不执行这句话也没有问题
|
//setTransformOriginPoint(m_boundingRect.center()); //变换中心默认为item的(0,0)点,所以不执行这句话也没有问题
|
||||||
//更改原点后自身绘制会在新坐标系下进行,会有跳转,所以需要将item整体做对应的移动
|
//更新bouondingRect后重回会显示位置会有变化,需要做对应的移动
|
||||||
moveBy(-delta.x(), -delta.y());
|
moveBy(-delta.x(), -delta.y());
|
||||||
updateHandles();
|
updateHandles();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastBoudingRect = m_boundingRect;
|
m_lastBoudingRect = m_boundingRect;
|
||||||
|
//qDebug() << "itemPos:" << mapToParent(pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
|
void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
|
||||||
|
|
@ -114,6 +115,7 @@ void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*
|
||||||
|
|
||||||
//绘制变换原点
|
//绘制变换原点
|
||||||
QPointF originPoint = transformOriginPoint();
|
QPointF originPoint = transformOriginPoint();
|
||||||
|
//qDebug() << "originPoint:" << originPoint;
|
||||||
painter->setBrush(Qt::red);
|
painter->setBrush(Qt::red);
|
||||||
painter->drawEllipse(originPoint, 4, 4);
|
painter->drawEllipse(originPoint, 4, 4);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "operationCommand.h"
|
#include "operationCommand.h"
|
||||||
|
#include "graphicsItem/graphicsItemGroup.h"
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
|
|
||||||
AddItemCommand::AddItemCommand(QGraphicsItem* item, QGraphicsScene* scene, QUndoCommand* parent)
|
AddItemCommand::AddItemCommand(QGraphicsItem* item, QGraphicsScene* scene, QUndoCommand* parent)
|
||||||
|
|
@ -39,8 +40,8 @@ void DeleteItemCommand::undo()
|
||||||
{
|
{
|
||||||
foreach(QGraphicsItem* item, m_listItem)
|
foreach(QGraphicsItem* item, m_listItem)
|
||||||
{
|
{
|
||||||
QGraphicsItemGroup* group = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
|
// QGraphicsItemGroup* group = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
|
||||||
if(!group)
|
// if(!group)
|
||||||
{
|
{
|
||||||
m_pGraphicsScene->addItem(item);
|
m_pGraphicsScene->addItem(item);
|
||||||
}
|
}
|
||||||
|
|
@ -52,8 +53,8 @@ void DeleteItemCommand::redo()
|
||||||
{
|
{
|
||||||
foreach(QGraphicsItem* item, m_listItem)
|
foreach(QGraphicsItem* item, m_listItem)
|
||||||
{
|
{
|
||||||
QGraphicsItemGroup* group = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
|
// QGraphicsItemGroup* group = dynamic_cast<QGraphicsItemGroup*>(item->parentItem());
|
||||||
if(!group)
|
// if(!group)
|
||||||
{
|
{
|
||||||
m_pGraphicsScene->removeItem(item); //remove即可,不要delete,因为会影响撤回(undo)操作
|
m_pGraphicsScene->removeItem(item); //remove即可,不要delete,因为会影响撤回(undo)操作
|
||||||
}
|
}
|
||||||
|
|
@ -62,3 +63,79 @@ void DeleteItemCommand::redo()
|
||||||
m_pGraphicsScene->update();
|
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<AbstractShape*>(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<AbstractShape*>(item);
|
||||||
|
ab->updateCoordinate();
|
||||||
|
ab->setSelected(true);
|
||||||
|
}
|
||||||
|
m_pGraphicsScene->removeItem(m_pGroup);
|
||||||
|
m_pGraphicsScene->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue