156 lines
4.9 KiB
C++
156 lines
4.9 KiB
C++
#include "graphicsItem/graphicsPolygonItem.h"
|
||
//#include "graphicsItem/itemControlHandle.h"
|
||
#include "graphicsItem/handleRect.h"
|
||
#include <QPainter>
|
||
#include <QStyleOption>
|
||
|
||
GraphicPolygonItem::GraphicPolygonItem(QGraphicsItem *parent)
|
||
: GraphicsProjectModelItem(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()
|
||
{
|
||
GraphicsProjectModelItem::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;
|
||
}
|