DiagramDesigner/diagramCavas/source/graphicsItem/graphicsPolygonItem.cpp

156 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "graphicsItem/graphicsPolygonItem.h"
//#include "graphicsItem/itemControlHandle.h"
#include "graphicsItem/handleRect.h"
#include <QPainter>
#include <QStyleOption>
GraphicPolygonItem::GraphicPolygonItem(QGraphicsItem *parent)
: GraphicsBaseItem(parent)
{
m_pen = QPen(Qt::black);
m_brush = QBrush(Qt::NoBrush);
}
GraphicPolygonItem::~GraphicPolygonItem()
{
}
QPainterPath GraphicPolygonItem::shape()
{
QPainterPath path;
path.addPolygon(m_points);
path.closeSubpath(); //将路径闭合
return path;
}
QRectF GraphicPolygonItem::boundingRect()
{
//m_boundingRect = shape().controlPointRect(); //返回路径中所有点和控制点的矩形文档介绍比返回精确边界框的boundingRect()函数计算要快
return m_boundingRect;
}
void GraphicPolygonItem::updateHandles()
{
GraphicsBaseItem::updateHandles();
for(int i = 0; i < m_points.size(); i++)
{
if(m_vecHanle.contains(H_edit + i -1))
{
m_vecHanle[H_edit + i -1]->move(m_points[i].x(), m_points[i].y());
}
}
}
void GraphicPolygonItem::updateCoordinate() //当执行了resie和editShape函数后boundingRect发生了变换需要将item的原点(以中心点为原点)校准至boundingRect.center()
{
if (!parentItem())
{
QPointF pt1, pt2, delta;
pt1 = mapToScene(QPointF(0, 0));
pt2 = mapToScene(m_boundingRect.center());
delta = pt1 - pt2;
prepareGeometryChange();
//更改图形绘制节点坐标,让图形中心和原点对齐
QPolygonF ptsOnScene = mapToScene(m_points); //所有操作都在scene坐标系下进行然后在还原至item坐标系否则会有跳转
for(int i=0; i<m_points.count(); i++)
ptsOnScene[i] += delta; //一定要在scene坐标系下执行操作不能直接m_points += delta;因为缩放以后item自身的内部坐标系也会同步缩放单位刻度和scene下的单位刻度不再一致所以所有相关计算一定要在同一个坐标系下完成
m_points = mapFromScene(ptsOnScene);
m_boundingRect = m_points.boundingRect();
//移动整体图形,消除节点坐标更后的绘制跳转
moveBy(-delta.x(), -delta.y());
updateHandles();
}
m_lastPoints = m_points;
}
void GraphicPolygonItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
painter->setPen(m_pen);
painter->setBrush(m_brush);
painter->drawPolygon(m_points);
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 GraphicPolygonItem::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_points = trans.map(m_lastPoints);
m_boundingRect = m_points.boundingRect();
m_dWidth = m_boundingRect.width();
m_dHeight = m_boundingRect.height();
updateHandles();
}
void GraphicPolygonItem::move(const QPointF& point)
{
moveBy(point.x(), point.y());
}
void GraphicPolygonItem::editShape(int nHandle,const QPointF& ptMouse)
{
QPointF pt = mapFromScene(ptMouse);
m_points[nHandle - H_rotate_leftBottom - 1] = pt;
prepareGeometryChange();
m_boundingRect = m_points.boundingRect();
m_dWidth = m_boundingRect.width();
m_dHeight = m_boundingRect.height();
m_lastPoints = m_points;
updateHandles();
}
void GraphicPolygonItem::addPoint(const QPointF& point)
{
m_points.append(mapFromScene(point));
int nCount = m_points.count();
//每个顶点都可以编辑所以一个顶点需要编辑handle
ItemControlHandle* pHandle = new HandleRect(this);
pHandle->setType(T_editShape);
pHandle->setTag(H_edit + nCount - 1);
m_vecHanle.insert(H_edit + nCount - 1,pHandle);
}
bool GraphicPolygonItem::endDrawing()
{
bool bSuccess = true;
int nPointCount = m_points.count();
if(nPointCount < 3)
bSuccess = false;
return bSuccess;
}