2024-08-16 11:39:30 +08:00
|
|
|
|
#include "graphicsItem/graphicsRectItem.h"
|
|
|
|
|
|
#include "graphicsItem/itemControlHandle.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QPainter>
|
2024-08-27 17:19:44 +08:00
|
|
|
|
#include <QStyleOption>
|
2024-08-16 11:39:30 +08:00
|
|
|
|
|
|
|
|
|
|
GraphicsRectItem::GraphicsRectItem(const QRect &rect, bool isRound, QGraphicsItem *parent)
|
|
|
|
|
|
: GraphicsBaseItem(parent), m_bIsRound(isRound), m_dRatioX(1 / 10.0), m_dRatioY(1 / 10.0)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pen = QPen(Qt::black);
|
|
|
|
|
|
m_brush = QBrush(Qt::NoBrush);
|
|
|
|
|
|
m_lastBoudingRect = rect;
|
|
|
|
|
|
m_boundingRect = rect;
|
|
|
|
|
|
m_dWidth = rect.width();
|
|
|
|
|
|
m_dHeight = rect.height();
|
|
|
|
|
|
|
|
|
|
|
|
if (m_bIsRound) //圆角矩形添加两个圆角大小控制点
|
|
|
|
|
|
{
|
|
|
|
|
|
//横轴X控制点
|
|
|
|
|
|
ItemControlHandle* pHandle1 = new ItemControlHandle(this);
|
|
|
|
|
|
pHandle1->setType(T_editShape);
|
|
|
|
|
|
pHandle1->setTag(H_edit);
|
|
|
|
|
|
m_vecHanle.push_back(pHandle1);
|
|
|
|
|
|
//纵轴Y控制点
|
|
|
|
|
|
ItemControlHandle* pHandle2 = new ItemControlHandle(this);
|
|
|
|
|
|
pHandle2->setType(T_editShape);
|
|
|
|
|
|
pHandle2->setTag(H_edit+1);
|
|
|
|
|
|
m_vecHanle.push_back(pHandle2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GraphicsRectItem::~GraphicsRectItem()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QPainterPath GraphicsRectItem::shape()
|
|
|
|
|
|
{
|
|
|
|
|
|
QPainterPath path;
|
|
|
|
|
|
double dHandleX = 0.0;
|
|
|
|
|
|
double dHandleY = 0.0;
|
|
|
|
|
|
if(m_dRatioX>0)
|
|
|
|
|
|
dHandleX = m_dWidth * m_dRatioX + 0.5;
|
|
|
|
|
|
if(m_dRatioY>0)
|
|
|
|
|
|
dHandleY = m_dHeight * m_dRatioY + 0.5;
|
|
|
|
|
|
|
|
|
|
|
|
if(m_bIsRound)
|
|
|
|
|
|
path.addRoundedRect(m_boundingRect, dHandleX, dHandleY);
|
|
|
|
|
|
else
|
|
|
|
|
|
path.addRect(m_boundingRect);
|
|
|
|
|
|
|
|
|
|
|
|
return path;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GraphicsRectItem::updateHandles()
|
|
|
|
|
|
{
|
|
|
|
|
|
GraphicsBaseItem::updateHandles();
|
|
|
|
|
|
if(m_bIsRound && m_vecHanle.size() == H_edit + 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
const QRectF& boundingRect = this->boundingRect();
|
|
|
|
|
|
//H_edit=9所以index号需要-1
|
|
|
|
|
|
m_vecHanle[H_edit -1]->move(boundingRect.right() - boundingRect.width() * m_dRatioX, boundingRect.top());
|
|
|
|
|
|
m_vecHanle[H_edit + 1 -1]->move(boundingRect.right(), boundingRect.top() + boundingRect.height() * m_dRatioY);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-20 19:42:42 +08:00
|
|
|
|
void GraphicsRectItem::updateCoordinate() //当执行了resie和editShape函数后,boundingRect发生了变换,需要将item的原点(以中心点为原点)校准至boundingRect.center()
|
2024-08-16 11:39:30 +08:00
|
|
|
|
{
|
|
|
|
|
|
QPointF pt1, pt2, delta;
|
2024-08-20 19:42:42 +08:00
|
|
|
|
pt1 = mapToScene(QPointF(0, 0));
|
2024-08-16 11:39:30 +08:00
|
|
|
|
pt2 = mapToScene(m_boundingRect.center());
|
|
|
|
|
|
delta = pt1 - pt2;
|
|
|
|
|
|
|
|
|
|
|
|
if (!parentItem())
|
|
|
|
|
|
{
|
|
|
|
|
|
prepareGeometryChange();
|
2024-08-20 19:42:42 +08:00
|
|
|
|
//boundingRect发生变化后原点偏离中心,将原点设为中心点
|
2024-08-16 11:39:30 +08:00
|
|
|
|
m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight);
|
2024-08-20 19:42:42 +08:00
|
|
|
|
//setTransformOriginPoint(m_boundingRect.center()); //变换中心默认为item的(0,0)点,所以不执行这句话也没有问题
|
|
|
|
|
|
//更改原点后自身绘制会在新坐标系下进行,会有跳转,所以需要将item整体做对应的移动
|
2024-08-16 11:39:30 +08:00
|
|
|
|
moveBy(-delta.x(), -delta.y());
|
|
|
|
|
|
updateHandles();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_lastBoudingRect = m_boundingRect;
|
|
|
|
|
|
}
|
2024-08-20 19:42:42 +08:00
|
|
|
|
|
2024-08-16 11:39:30 +08:00
|
|
|
|
void GraphicsRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
|
|
|
|
|
|
{
|
|
|
|
|
|
painter->setPen(m_pen);
|
|
|
|
|
|
painter->setBrush(m_brush);
|
|
|
|
|
|
|
|
|
|
|
|
if(m_bIsRound)
|
|
|
|
|
|
{
|
|
|
|
|
|
double dRadiusX = 0.0;
|
|
|
|
|
|
double dRadiusY = 0.0;
|
|
|
|
|
|
if(m_dRatioX>0)
|
|
|
|
|
|
dRadiusX = m_dWidth * m_dRatioX + 0.5;
|
|
|
|
|
|
if(m_dRatioY>0)
|
|
|
|
|
|
dRadiusY = m_dHeight * m_dRatioY + 0.5;
|
|
|
|
|
|
|
|
|
|
|
|
painter->drawRoundedRect(m_boundingRect, dRadiusX, dRadiusY);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
painter->drawRect(m_boundingRect);
|
2024-08-20 19:42:42 +08:00
|
|
|
|
|
|
|
|
|
|
//绘制变换原点
|
2024-08-27 17:19:44 +08:00
|
|
|
|
QPointF originPoint = transformOriginPoint();
|
|
|
|
|
|
painter->setBrush(Qt::red);
|
|
|
|
|
|
painter->drawEllipse(originPoint, 4, 4);
|
|
|
|
|
|
|
|
|
|
|
|
if (option->state & QStyle::State_Selected) //是选中状态,绘制选中框
|
|
|
|
|
|
{
|
|
|
|
|
|
int nPenWidth = 1;
|
|
|
|
|
|
painter->setPen(QPen(QColor(70,70,70), nPenWidth, Qt::DashLine)); //蓝色的外框
|
|
|
|
|
|
painter->setBrush(Qt::NoBrush);
|
|
|
|
|
|
painter->drawRect(m_boundingRect_selected);
|
|
|
|
|
|
}
|
2024-08-16 11:39:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GraphicsRectItem::resize(int nHandle,double dSX, double dSY, const QPointF& basePoint)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (nHandle)
|
|
|
|
|
|
{
|
|
|
|
|
|
case H_left:
|
|
|
|
|
|
case H_right:
|
|
|
|
|
|
dSY = 1; //拖拽的是左点右点,为水平缩放,忽略垂直变化
|
|
|
|
|
|
break;
|
|
|
|
|
|
case H_top:
|
|
|
|
|
|
case H_bottom:
|
|
|
|
|
|
dSX = 1; //拖拽的是顶点底点,为垂直缩放,忽略水平变化
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QTransform trans;
|
|
|
|
|
|
//缩放是以图元原点(中心)位置为基准,所以每帧都先移动移动到想要的基准点,缩放之后再移回
|
|
|
|
|
|
trans.translate(basePoint.x(), basePoint.y());
|
|
|
|
|
|
trans.scale(dSX, dSY);
|
|
|
|
|
|
trans.translate(-basePoint.x(), -basePoint.y());
|
|
|
|
|
|
|
|
|
|
|
|
prepareGeometryChange();
|
|
|
|
|
|
m_boundingRect = trans.mapRect(m_lastBoudingRect);
|
|
|
|
|
|
m_dWidth = m_boundingRect.width();
|
|
|
|
|
|
m_dHeight = m_boundingRect.height();
|
|
|
|
|
|
updateHandles();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GraphicsRectItem::move(const QPointF& point)
|
|
|
|
|
|
{
|
|
|
|
|
|
moveBy(point.x(), point.y());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GraphicsRectItem::editShape(int nHandle,const QPointF& ptMouse)
|
|
|
|
|
|
{
|
2024-08-20 19:42:42 +08:00
|
|
|
|
QPointF ptOnItem = mapFromParent(ptMouse);
|
2024-08-16 11:39:30 +08:00
|
|
|
|
switch (nHandle)
|
|
|
|
|
|
{
|
|
|
|
|
|
//横轴X控制点
|
|
|
|
|
|
case H_edit:
|
|
|
|
|
|
{
|
2024-08-20 19:42:42 +08:00
|
|
|
|
double dMouseX = ptOnItem.x();
|
2024-08-16 11:39:30 +08:00
|
|
|
|
if(dMouseX < m_boundingRect.center().x())
|
|
|
|
|
|
dMouseX = m_boundingRect.center().x();
|
|
|
|
|
|
else if(dMouseX > m_boundingRect.right())
|
|
|
|
|
|
dMouseX = m_boundingRect.right();
|
|
|
|
|
|
double dWidth = m_boundingRect.width();
|
|
|
|
|
|
if(dWidth == 0.0)
|
|
|
|
|
|
dWidth = 1.0;
|
|
|
|
|
|
m_dRatioX = (m_boundingRect.right() - dMouseX) / dWidth;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
//纵轴Y控制点
|
|
|
|
|
|
case H_edit + 1:
|
|
|
|
|
|
{
|
2024-08-20 19:42:42 +08:00
|
|
|
|
double dMouseY = ptOnItem.y();
|
2024-08-16 11:39:30 +08:00
|
|
|
|
if(dMouseY > m_boundingRect.center().y())
|
|
|
|
|
|
dMouseY = m_boundingRect.center().y();
|
|
|
|
|
|
else if(dMouseY < m_boundingRect.top())
|
|
|
|
|
|
dMouseY = m_boundingRect.top();
|
|
|
|
|
|
double dHeight = m_boundingRect.height();
|
|
|
|
|
|
if(dHeight == 0.0)
|
|
|
|
|
|
dHeight = 1.0;
|
|
|
|
|
|
m_dRatioY = (dMouseY - m_boundingRect.top()) / dHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
prepareGeometryChange();
|
|
|
|
|
|
updateHandles();
|
|
|
|
|
|
}
|