#include "graphicsItem/graphicsRectItem.h" #include "graphicsItem/itemControlHandle.h" #include #include 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); } } void GraphicsRectItem::updateCoordinate() //当执行了resie和editShape函数后,boundingRect发生了变换,需要将item的原点(以中心点为原点)校准至boundingRect.center() { QPointF pt1, pt2, delta; pt1 = mapToScene(QPointF(0, 0)); pt2 = mapToScene(m_boundingRect.center()); delta = pt1 - pt2; if (!parentItem()) { prepareGeometryChange(); //boundingRect发生变化后原点偏离中心,将原点设为中心点 m_boundingRect = QRectF(-m_dWidth / 2, -m_dHeight / 2, m_dWidth, m_dHeight); //setTransformOriginPoint(m_boundingRect.center()); //变换中心默认为item的(0,0)点,所以不执行这句话也没有问题 //更改原点后自身绘制会在新坐标系下进行,会有跳转,所以需要将item整体做对应的移动 moveBy(-delta.x(), -delta.y()); updateHandles(); } m_lastBoudingRect = m_boundingRect; } 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); 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); //绘制变换原点 QPointF originPoint = transformOriginPoint(); painter->setBrush(Qt::red); painter->drawEllipse(originPoint, 4, 4); } } 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) { QPointF ptOnItem = mapFromParent(ptMouse); switch (nHandle) { //横轴X控制点 case H_edit: { double dMouseX = ptOnItem.x(); 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: { double dMouseY = ptOnItem.y(); 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(); }