#ifndef GRAPHICSBASEITEM_H #define GRAPHICSBASEITEM_H #include "itemControlHandle.h" #include #include #include #include enum ShapeType { T_undefined, T_item, T_group }; //基类采用模板形式,QGraphicsItem是默认值,也可以是别的类型,比如QGraphicsItemGroup,这样不同的基类继承可以共用一些高层的行为定义 template class AbstractShapeType : public BaseType { public: explicit AbstractShapeType(QGraphicsItem *parent = 0) : BaseType(parent) { m_type = T_undefined; m_pen = QPen(Qt::NoPen); m_brush = QBrush(QColor(rand() % 32 * 8, rand() % 32 * 8, rand() % 32 * 8)); m_dWidth = m_dHeight = 0; m_pOperationCopy = nullptr; } virtual ~AbstractShapeType() { for (size_t i = 0; i < m_vecHanle.size(); i++) { ItemControlHandle* pHandle = m_vecHanle[i]; if (pHandle) { delete pHandle; pHandle = nullptr; } } } public: virtual ShapeType getType() {return m_type;} QPen pen() { return m_pen; } void setPen(const QPen &pen) { m_pen = pen; } QColor penColor() { return m_pen.color(); } void setPenColor(const QColor &color) { m_pen.setColor(color); } QBrush brush() { return m_brush; } void setBrush(const QBrush &brush) { m_brush = brush; } QColor brushColor() { return m_brush.color(); } void setBrushColor(const QColor &color) { m_brush.setColor(color); } double width() { return m_dWidth; } void setWidth(double width) { m_dWidth = width; updateCoordinate(); } double height() { return m_dHeight; } void setHeight(double height) { m_dHeight = height; updateCoordinate(); } int collidesWithHandle(const QPointF& point) { for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) { QPointF pt = (*it)->mapFromScene(point); if((*it)->contains(pt)) return (*it)->getTag(); } return HandleTag::H_none; } //操作副本相关 virtual void createOperationCopy() {} virtual void removeOperationCopy() {} virtual void moveOperationCopy(const QPointF&) {} virtual void rotateOperationCopy(const double&) {} virtual void resize(int,double, double, const QPointF&) {} virtual void move(const QPointF&) {} virtual void editShape(int, const QPointF&) {} virtual void updateCoordinate() {} //handle相关 virtual int handleCount() { return m_vecHanle.count(); } virtual ItemControlHandle* getHandle(int nHandle) { ItemControlHandle* handle = nullptr; for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) { if((*it)->getTag() == nHandle) { handle = (*it); return handle; } } return handle; } virtual void setHandleVisible(bool bVisible) { for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) { if(bVisible) (*it)->show(); else (*it)->hide(); } } virtual QPointF getSymmetricPointPos(int nHandle) //获取对称点的坐标位置,缩放的时候需要以对称点为锚点 { QPointF pt; //编号从1开始,因此下标需要-1 switch (nHandle) { case H_leftTop: pt = m_vecHanle.at(H_rightBottom - 1)->pos(); break; case H_top: pt = m_vecHanle.at(H_bottom - 1)->pos(); break; case H_rightTop: pt = m_vecHanle.at(H_leftBottom - 1)->pos(); break; case H_right: pt = m_vecHanle.at(H_left - 1)->pos(); break; case H_rightBottom: pt = m_vecHanle.at(H_leftTop - 1)->pos(); break; case H_bottom: pt = m_vecHanle.at(H_top - 1)->pos(); break; case H_leftBottom: pt = m_vecHanle.at(H_rightTop - 1)->pos(); break; case H_left: pt = m_vecHanle.at(H_right - 1)->pos(); break; default: break; } return pt; } virtual void updateHandles() { int nMargin = 5; const QRectF& boundRect = this->boundingRect(); for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) { switch ((*it)->getTag()) { case H_leftTop: (*it)->move(boundRect.x() - nMargin, boundRect.y() - nMargin); break; case H_top: (*it)->move(boundRect.x() + boundRect.width() * 0.5, boundRect.y() - nMargin); break; case H_rightTop: (*it)->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() - nMargin); break; case H_right: (*it)->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() + boundRect.height() * 0.5 + nMargin); break; case H_rightBottom: (*it)->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() + boundRect.height() + nMargin); break; case H_bottom: (*it)->move(boundRect.x() + boundRect.width() * 0.5, boundRect.y() + boundRect.height()+ nMargin); break; case H_leftBottom: (*it)->move(boundRect.x() - nMargin, boundRect.y() + boundRect.height() + nMargin); break; case H_left: (*it)->move(boundRect.x() - nMargin, boundRect.y() + boundRect.height() * 0.5); break; case H_rotate_leftTop: { ItemControlHandle* handle = getHandle(H_leftTop); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); (*it)->move(pt.x() - nSize - 1, pt.y() - nSize - 1); } else (*it)->setVisible(false); break; } case H_rotate_rightTop: { ItemControlHandle* handle = getHandle(H_rightTop); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); (*it)->move(pt.x() + nSize + 1, pt.y() - nSize - 1); } else (*it)->setVisible(false); break; } case H_rotate_rightBottom: { ItemControlHandle* handle = getHandle(H_rightBottom); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); (*it)->move(pt.x() + nSize + 1, pt.y() + nSize + 1); } else (*it)->setVisible(false); break; } case H_rotate_leftBottom: { ItemControlHandle* handle = getHandle(H_leftBottom); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); (*it)->move(pt.x() - nSize - 1, pt.y() + nSize + 1); } else (*it)->setVisible(false); break; } default: break; } } m_boundingRect_selected = boundRect.adjusted(-nMargin, -nMargin, nMargin, nMargin); } virtual QRectF boundingRect() const { return m_boundingRect; } virtual QPainterPath shape() { QPainterPath path; return path; } protected: ShapeType m_type; QPen m_pen; QBrush m_brush; double m_dWidth; double m_dHeight; QRectF m_boundingRect; QRectF m_boundingRect_selected;//选中矩形框 QGraphicsPathItem* m_pOperationCopy; //图元移动和旋转时的操作副本 QPointF m_movingIniPos; //移动副本开始移动初始点 QVector m_vecHanle; }; typedef AbstractShapeType AbstractShape; class GraphicsBaseItem : public QObject, public AbstractShapeType { Q_OBJECT public: GraphicsBaseItem(QGraphicsItem *parent); virtual ~GraphicsBaseItem(); virtual void createOperationCopy(); virtual void removeOperationCopy(); virtual void moveOperationCopy(const QPointF&); virtual void rotateOperationCopy(const double&); //多边形、线段等点选创建的对象需要的函数 virtual void addPoint(const QPointF&) {} virtual bool endDrawing() { return true; } protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&); virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*); }; #endif