yangjingjing 5 年之前
當前提交
308e262ccb
共有 100 個文件被更改,包括 5609 次插入0 次删除
  1. 140 0
      GraphicsArrowItem.cpp
  2. 28 0
      GraphicsArrowItem.h
  3. 27 0
      GraphicsEllipseItem.cpp
  4. 14 0
      GraphicsEllipseItem.h
  5. 115 0
      GraphicsItem.cpp
  6. 65 0
      GraphicsItem.h
  7. 66 0
      GraphicsItemGroup.cpp
  8. 15 0
      GraphicsItemGroup.h
  9. 11 0
      GraphicsLineItem.cpp
  10. 10 0
      GraphicsLineItem.h
  11. 108 0
      GraphicsPathItem.cpp
  12. 29 0
      GraphicsPathItem.h
  13. 104 0
      GraphicsPixmapItem.cpp
  14. 30 0
      GraphicsPixmapItem.h
  15. 103 0
      GraphicsRectItem.cpp
  16. 44 0
      GraphicsRectItem.h
  17. 40 0
      GraphicsTextItem.cpp
  18. 24 0
      GraphicsTextItem.h
  19. 35 0
      GraphicsTriangleItem.cpp
  20. 13 0
      GraphicsTriangleItem.h
  21. 217 0
      ImageEdit.cpp
  22. 74 0
      ImageEdit.h
  23. 784 0
      ImageEdit.ui
  24. 189 0
      MainPaintScene.cpp
  25. 61 0
      MainPaintScenee.h
  26. 365 0
      PaintView.cpp
  27. 45 0
      PaintView.h
  28. 21 0
      PaintWidget.ui
  29. 16 0
      ShapeMimeData.cpp
  30. 13 0
      ShapeMimeData.h
  31. 35 0
      WordEdit.cpp
  32. 79 0
      WordEdit.ui
  33. 22 0
      WordEditt.h
  34. 626 0
      drawtool.cpp
  35. 147 0
      drawtool.h
  36. 86 0
      handprint_identification_reports.pro
  37. 3 0
      handprint_identification_reports_zh_CN.ts
  38. 150 0
      hmerge.cpp
  39. 34 0
      hmerge.h
  40. 45 0
      hmerge.ui
  41. 484 0
      imagecropperdemo.cpp
  42. 91 0
      imagecropperdemo.h
  43. 99 0
      imagecropperdialog.h
  44. 714 0
      imagecropperlabel.cpp
  45. 165 0
      imagecropperlabel.h
  46. 二進制
      images/arrows.ico
  47. 二進制
      images/backimage.jpg
  48. 二進制
      images/bohui.png
  49. 二進制
      images/close.png
  50. 二進制
      images/color-palette.ico
  51. 二進制
      images/cursor.ico
  52. 二進制
      images/delete.ico
  53. 二進制
      images/delete.png
  54. 二進制
      images/draw.ico
  55. 二進制
      images/drawtool.ico
  56. 二進制
      images/ellipse.ico
  57. 二進制
      images/expand.png
  58. 二進制
      images/font.png
  59. 二進制
      images/ic_click_recording.png
  60. 二進制
      images/ic_cutover_close.png
  61. 二進制
      images/ic_drawing_beeline.png
  62. 二進制
      images/ic_drawing_round.png
  63. 二進制
      images/ic_drawing_square.png
  64. 二進制
      images/ic_drawing_triangle.png
  65. 二進制
      images/ic_enlarge.png
  66. 二進制
      images/ic_expand.png
  67. 二進制
      images/ic_gaotu.png
  68. 二進制
      images/ic_green_correct.png
  69. 二進制
      images/ic_increase.png
  70. 二進制
      images/ic_navigation_help.png
  71. 二進制
      images/ic_next.png
  72. 二進制
      images/ic_phone.png
  73. 二進制
      images/ic_previous.png
  74. 二進制
      images/ic_put away.png
  75. 二進制
      images/ic_recording_process.png
  76. 二進制
      images/ic_red_error.png
  77. 二進制
      images/ic_return.png
  78. 二進制
      images/ic_shrink.png
  79. 二進制
      images/ic_sidebar_arrow.png
  80. 二進制
      images/ic_sidebar_checked.png
  81. 二進制
      images/ic_sidebar_color.png
  82. 二進制
      images/ic_sidebar_image.png
  83. 二進制
      images/ic_sidebar_pencil.png
  84. 二進制
      images/ic_sidebar_shape.png
  85. 二進制
      images/ic_sidebar_text.png
  86. 二進制
      images/ic_sort.png
  87. 二進制
      images/ic_square_selected.png
  88. 二進制
      images/ic_square_unselected.png
  89. 二進制
      images/ic_top bar_narrow.png
  90. 二進制
      images/ic_turn left.png
  91. 二進制
      images/ic_turn right.png
  92. 23 0
      images/images.qrc
  93. 二進制
      images/input.png
  94. 二進制
      images/input_select.png
  95. 二進制
      images/line.ico
  96. 二進制
      images/open.ico
  97. 二進制
      images/open.png
  98. 二進制
      images/pause.png
  99. 二進制
      images/pixmap.ico
  100. 二進制
      images/play.png

+ 140 - 0
GraphicsArrowItem.cpp

@@ -0,0 +1,140 @@
+#include "GraphicsArrowItem.h"
+
+
+GraphicsArrowItem::GraphicsArrowItem(const QPointF &start,
+                                     const QPointF &end,
+                                     QGraphicsItem *parent)
+    : QGraphicsItem(parent)
+{
+    len = 16;
+    startPos = start;
+    endPos = end;
+}
+
+QRectF GraphicsArrowItem::boundingRect() const
+{
+    QPainterPath path = getArrowsPath(startPos, endPos, len);
+    return path.controlPointRect();
+}
+
+void GraphicsArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *w)
+{
+    QPen pen =painter->pen();
+    pen.setWidth(4);
+    pen.setColor(_mColor);
+    painter->setPen(pen);
+    if(startPos !=endPos)
+    {
+        QPainterPath path = getArrowsPath(startPos, endPos, len);
+        painter->drawPath(path);
+    }
+}
+
+QLineF getEllipseAndLineNodes(qreal k, qreal b, qreal c, qreal d, qreal r)
+{
+    // 求圆和直线的交点坐标
+    // y = kx +b
+    // (x+c)^2 + (y+d)^2 = r^2
+    qreal temp1 = sqrt((k*k+1)*r*r - c*c*k*k + (2*c*d + 2*b*c)*k - d*d -2*b*d -b*b);
+    qreal temp2 = (d+b)*k+c;
+    qreal temp3 = k*k + 1;
+    qreal x1 = -(temp1 + temp2) / temp3;
+    qreal x2 = (temp1 - temp2) / temp3;
+
+    qreal temp4 = sqrt(k*k*r*r + r*r - c*c*k*k + 2*c*d*k + 2*b*c*k - d*d - 2*b*d - b*b);
+    qreal y1 = -(k*(c+temp4) +d*k*k-b) / temp3;
+    qreal y2 = -(k*(c-temp4) +d*k*k-b) / temp3;
+
+    return QLineF(QPointF(x1, y1), QPointF(x2, y2));
+}
+
+QLineF getVerticalLine(const QPointF &start,
+                       const QPointF &end,
+                       qreal distance,
+                       qreal len)
+{
+    // 直线方程: y = kx + b
+    if (end.y() != start.y() && end.x() != start.x()) // 不垂直X轴
+    {
+        qreal k = (start.y() - end.y()) / (start.x() - end.x());
+        qreal b = start.y() - k * start.x();
+
+        qreal c = -start.x();
+        qreal d = -start.y();
+        qreal r = distance;
+        // 求圆和直线的交点坐标
+        QLineF nodes = getEllipseAndLineNodes(k, b, c, d, r);
+
+        qreal x,y; //交点
+        if (start.x() > end.x())
+        {
+            if (nodes.x1() < nodes.x2())
+            {
+                x = nodes.x1();
+                y = nodes.y1();
+            }
+            else
+            {
+                x = nodes.x2();
+                y = nodes.y2();
+            }
+        }
+        else
+        {
+            if (nodes.x1() > nodes.x2())
+            {
+                x = nodes.x1();
+                y = nodes.y1();
+            }
+            else
+            {
+                x = nodes.x2();
+                y = nodes.y2();
+            }
+        }
+
+        qreal k1 = -1/k;
+        qreal b1 = y - k1 * x;
+        qreal c1 = -x;
+        qreal d1 = -y;
+        qreal r1 = len / 2;
+        return getEllipseAndLineNodes(k1, b1, c1, d1, r1);
+    }
+    else
+    {
+        QLineF line;
+        int dire;
+        if (end.x() == start.x())
+        {
+            dire = end.y() > start.y() ? 1:-1;
+            line = QLineF(QPointF(start.x() - len / 2, start.y() + (distance * dire)),
+                          QPointF(start.x() + len / 2, start.y() + (distance * dire)));
+        }
+        else
+        {
+            dire = end.x() > start.x() ? 1:-1;
+            line = QLineF(QPointF(start.x() + (distance * dire), start.y() - len / 2),
+                          QPointF(start.x() + (distance * dire), start.y() + len / 2));
+        }
+        return line;
+    }
+}
+QPainterPath GraphicsArrowItem::getArrowsPath(const QPointF &start,
+                                              const QPointF &end,
+                                              qreal len) const
+{
+    QPainterPath path;
+    path.moveTo(startPos);
+
+    QLineF line1 = getVerticalLine(endPos, startPos, len * sqrt(3) / 2, len / 2);
+    QLineF line2 = getVerticalLine(endPos, startPos, len * sqrt(3) / 2, len);
+
+    path.lineTo(line1.p1());
+    path.lineTo(line2.p1());
+    path.lineTo(endPos);
+    path.lineTo(line2.p2());
+    path.lineTo(line1.p2());
+    path.lineTo(startPos);
+
+    return path;
+}

+ 28 - 0
GraphicsArrowItem.h

@@ -0,0 +1,28 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsItem.h"
+class GraphicsArrowItem : public QGraphicsItem
+{
+public:
+    GraphicsArrowItem(const QPointF &start = QPointF(),
+                      const QPointF &end = QPointF(),
+                      QGraphicsItem * parent=0);
+    QRectF boundingRect() const Q_DECL_OVERRIDE;
+    void paint(QPainter *painter,
+               const QStyleOptionGraphicsItem *option,
+               QWidget *w) Q_DECL_OVERRIDE;
+    QPointF startPos,endPos;
+    void setBorderColor(QColor color)
+    {
+        _mColor =color;
+    }
+private:
+    QPainterPath getArrowsPath(const QPointF &start,
+                               const QPointF &end,
+                               qreal len) const;
+
+
+private:
+    qreal   len;
+    QColor _mColor;
+};

+ 27 - 0
GraphicsEllipseItem.cpp

@@ -0,0 +1,27 @@
+#include "GraphicsEllipseItem.h"
+
+
+
+GraphicsEllipseItem::GraphicsEllipseItem(const QRect &rect, QGraphicsItem *parent)
+    :GraphicsRectItem(rect,parent)
+{
+
+}
+
+QPainterPath GraphicsEllipseItem::shape() const
+{
+    QPainterPath path;
+    path.addEllipse(boundingRect());
+    return qt_graphicsItem_shapeFromPath(path,_pen);
+}
+
+void GraphicsEllipseItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    QRectF rc = rect();
+    QPen pen =painter->pen();
+    pen.setWidth(4);
+    painter->setPen(pen);
+    painter->setPen(m_color);
+    painter->drawEllipse(rc);
+}
+

+ 14 - 0
GraphicsEllipseItem.h

@@ -0,0 +1,14 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsRectItem.h"
+
+
+class GraphicsEllipseItem : public GraphicsRectItem
+{
+public:
+    GraphicsEllipseItem(const QRect & rect ,QGraphicsItem * parent);
+    QPainterPath shape() const;
+
+protected:
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+};

+ 115 - 0
GraphicsItem.cpp

@@ -0,0 +1,115 @@
+#include "GraphicsItem.h"
+GraphicsItem::GraphicsItem(QGraphicsItem *parent)
+    :QAbstractGraphicsShapeItem(parent)
+{
+    // QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
+    // effect->setBlurRadius(8);
+    // setGraphicsEffect(effect);
+}
+
+void GraphicsItem::updateGeometry()
+{
+    const QRectF &geom = this->boundingRect();
+
+    const int w = SELECTION_HANDLE_SIZE;
+    const int h = SELECTION_HANDLE_SIZE;
+
+    const Handles::iterator hend =  m_handles.end();
+    for (Handles::iterator it = m_handles.begin(); it != hend; ++it) {
+        SizeHandleRect *hndl = *it;;
+        switch (hndl->dir()) {
+        case SizeHandleRect::LeftTop:
+            hndl->move(geom.x() - w / 2, geom.y() - h / 2);
+            break;
+        case SizeHandleRect::Top:
+            hndl->move(geom.x() + geom.width() / 2 - w / 2, geom.y() - h / 2);
+            break;
+        case SizeHandleRect::RightTop:
+            hndl->move(geom.x() + geom.width() - w / 2, geom.y() - h / 2);
+            break;
+        case SizeHandleRect::Right:
+            hndl->move(geom.x() + geom.width() - w / 2, geom.y() + geom.height() / 2 - h / 2);
+            break;
+        case SizeHandleRect::RightBottom:
+            hndl->move(geom.x() + geom.width() - w / 2, geom.y() + geom.height() - h / 2);
+            break;
+        case SizeHandleRect::Bottom:
+            hndl->move(geom.x() + geom.width() / 2 - w / 2, geom.y() + geom.height() - h / 2);
+            break;
+        case SizeHandleRect::LeftBottom:
+            hndl->move(geom.x() - w / 2, geom.y() + geom.height() - h / 2);
+            break;
+        case SizeHandleRect::Left:
+            hndl->move(geom.x() - w / 2, geom.y() + geom.height() / 2 - h / 2);
+            break;
+        case SizeHandleRect::Center:
+            hndl->move(geom.center().x()  - w / 2 , geom.center().y() - h / 2);
+            break;
+        default:
+            break;
+        }
+    }
+
+}
+
+void GraphicsItem::setState(SelectionHandleState st)
+{
+    const Handles::iterator hend =  m_handles.end();
+    for (Handles::iterator it = m_handles.begin(); it != hend; ++it)
+        (*it)->setState(st);
+}
+
+SizeHandleRect::Direction GraphicsItem::hitTest(const QPointF &point) const
+{
+    const Handles::const_iterator hend =  m_handles.end();
+    for (Handles::const_iterator it = m_handles.begin(); it != hend; ++it)
+    {
+        if ((*it)->hitTest(point) ){
+            return (*it)->dir();
+        }
+    }
+    return SizeHandleRect::None;
+}
+
+Qt::CursorShape GraphicsItem::getCursor(SizeHandleRect::Direction dir)
+{
+    switch (dir) {
+    case SizeHandleRect::Right:
+        return Qt::SizeHorCursor;
+    case SizeHandleRect::RightTop:
+        return Qt::SizeBDiagCursor;
+    case SizeHandleRect::RightBottom:
+        return Qt::SizeFDiagCursor;
+    case SizeHandleRect::LeftBottom:
+        return Qt::SizeBDiagCursor;
+    case SizeHandleRect::Bottom:
+        return Qt::SizeVerCursor;
+    case SizeHandleRect::LeftTop:
+        return Qt::SizeFDiagCursor;
+    case SizeHandleRect::Left:
+        return Qt::SizeHorCursor;
+    case SizeHandleRect::Top:
+        return Qt::SizeVerCursor;
+    default:
+        break;
+    }
+    return Qt::ArrowCursor;
+}
+
+void GraphicsItem::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
+{
+
+}
+
+QVariant GraphicsItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+    if ( change == QGraphicsItem::ItemSelectedHasChanged ) {
+        qDebug()<<" Item Selected : " << value.toString();
+        setState(value.toBool() ? SelectionHandleActive : SelectionHandleOff);
+    }else if ( change == QGraphicsItem::ItemRotationHasChanged ){
+        qDebug()<<"Item Rotation Changed:" << value.toString();
+    }else if ( change == QGraphicsItem::ItemTransformOriginPointHasChanged ){
+        qDebug()<<"ItemTransformOriginPointHasChanged:" << value.toPointF();
+    }
+    return value;
+}

+ 65 - 0
GraphicsItem.h

@@ -0,0 +1,65 @@
+#pragma once
+#include "preheader.h"
+#include "sizehandle.h"
+#define M_PI 3.14159265358979323846
+static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen)
+{
+    // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
+    // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
+    const qreal penWidthZero = qreal(0.00000001);
+
+    if (path == QPainterPath() || pen == Qt::NoPen)
+        return path;
+    QPainterPathStroker ps;
+    ps.setCapStyle(pen.capStyle());
+
+    ps.setWidth(pen.widthF());
+    ps.setJoinStyle(pen.joinStyle());
+    ps.setMiterLimit(pen.miterLimit());
+    QPainterPath p = ps.createStroke(path);
+    p.addPath(path);
+    return p;
+
+}
+
+class GraphicsItem : public QAbstractGraphicsShapeItem
+{
+public:
+    GraphicsItem(QGraphicsItem * parent );
+    enum {Type = UserType+1};
+    int  type() const { return Type; }
+    SizeHandleRect::Direction  hitTest( const QPointF & point ) const;
+    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
+    virtual QPointF origin () const { return QPointF(0,0); }
+    virtual Qt::CursorShape getCursor(SizeHandleRect::Direction dir );
+    virtual QRectF  rect() const { return QRectF(0,0,0,0);}
+    virtual void resetShape(){}
+    void resetArrow()
+    {
+        if(m_rect.top()>m_rect.bottom())
+        {
+            qreal tmp =m_rect.bottom();
+            m_rect.setBottom(m_rect.top());
+            m_rect.setTop(tmp);
+        }
+        if(m_rect.left()>m_rect.right())
+        {
+            qreal tmp =m_rect.right();
+            m_rect.setRight(m_rect.left());
+            m_rect.setLeft(tmp);
+        }
+        updateGeometry();
+    }
+
+
+protected:
+    virtual void updateGeometry();
+    void setState(SelectionHandleState st);
+    virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event){}
+    QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+    typedef QVector<SizeHandleRect*> Handles;
+    Handles m_handles;
+    QRectF m_rect;
+    QPen _pen;
+    QColor _color =Qt::red;
+};

+ 66 - 0
GraphicsItemGroup.cpp

@@ -0,0 +1,66 @@
+#include "GraphicsItemGroup.h"
+
+
+GraphicsItemGroup::GraphicsItemGroup(QGraphicsItemGroup *group, QGraphicsItem *parent)
+    :GraphicsRectItem(QRect(0,0,0,0),parent )
+    ,m_group(group)
+{
+    if ( m_group ){
+        m_group->setParentItem(this);
+        QRectF bound = m_group->boundingRect();
+
+        qDebug()<<" group rect :" << m_group->boundingRect() << " new Rect:" << bound;
+        bound.normalized();
+        prepareGeometryChange();
+        m_width = bound.width();
+        m_height = bound.height();
+
+        QPointF delta = pos() - bound.center() ;
+
+        setTransform(transform().translate(delta.x(),delta.y()));
+        setTransformOriginPoint( bound.center());
+        moveBy(-delta.x(),-delta.y());
+
+        m_group->setTransformOriginPoint(bound.center());
+
+        qDebug()<<"pos :" << delta;
+        updateGeometry();
+    }
+}
+
+QRectF GraphicsItemGroup::boundingRect() const
+{
+
+    QRectF bounding = m_group->mapRectToParent(m_group->boundingRect());
+
+    return bounding;
+}
+
+QPainterPath GraphicsItemGroup::shape() const
+{
+    return m_group->shape() ;
+}
+
+void GraphicsItemGroup::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
+{
+
+}
+
+void GraphicsItemGroup::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    QPointF origin = mapFromScene(pos());
+
+    QPointF origin1 = m_group->transformOriginPoint();
+
+    QColor c1 = QColor(Qt::blue);
+  //  c1.setAlpha(180);
+    painter->setBrush(c1);
+    painter->drawEllipse(origin.x() - 3 , origin.y() - 3 ,6,6);
+
+
+    QColor c2 = QColor(Qt::green);
+  //  c2.setAlpha(180);
+    painter->setBrush(c2);
+    painter->drawEllipse(origin1.x() - 3 , origin1.y() - 3 ,6,6);
+
+}

+ 15 - 0
GraphicsItemGroup.h

@@ -0,0 +1,15 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsRectItem.h"
+
+class GraphicsItemGroup : public GraphicsRectItem
+{
+public:
+    GraphicsItemGroup ( QGraphicsItemGroup * group, QGraphicsItem * parent );
+    QRectF boundingRect() const;
+    QPainterPath shape() const;
+    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
+protected:
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+    QGraphicsItemGroup *m_group;
+};

+ 11 - 0
GraphicsLineItem.cpp

@@ -0,0 +1,11 @@
+#include "GraphicsLineItem.h"
+
+GraphicsLineItem::GraphicsLineItem(const QLineF &line,QGraphicsItem *parent)
+    :QGraphicsLineItem(line,parent)
+{
+    setFlag(QGraphicsItem::ItemIsMovable, true);
+    setFlag(QGraphicsItem::ItemIsSelectable, true);
+    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+    this->setAcceptHoverEvents(true);
+}
+

+ 10 - 0
GraphicsLineItem.h

@@ -0,0 +1,10 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsRectItem.h"
+
+class GraphicsLineItem : public QGraphicsLineItem
+{
+public:
+    GraphicsLineItem(const QLineF &line,QGraphicsItem * parent=0 );
+
+};

+ 108 - 0
GraphicsPathItem.cpp

@@ -0,0 +1,108 @@
+#include "GraphicsPathItem.h"
+
+GraphicsPathItem::GraphicsPathItem(const QPainterPath &path ,GraphicsItem *parent) :
+    GraphicsItem(parent)
+  ,_path(path)
+  ,m_width(_path.boundingRect().width())
+  ,m_height(_path.boundingRect().height())
+
+{
+    m_handles.reserve(SizeHandleRect::None);
+    for (int i = SizeHandleRect::LeftTop; i <= SizeHandleRect::Left; ++i) {
+        SizeHandleRect *shr = new SizeHandleRect(this, static_cast<SizeHandleRect::Direction>(i), this);
+        m_handles.push_back(shr);
+    }
+    updateGeometry();
+    _boundingRect =_path.controlPointRect();
+    setFlag(QGraphicsItem::ItemIsMovable, true);
+    setFlag(QGraphicsItem::ItemIsSelectable, true);
+    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+    this->setAcceptHoverEvents(true);
+}
+
+QRectF GraphicsPathItem::boundingRect() const
+{
+    if (_boundingRect.isNull()) {
+        qreal pw = _pen.style() == Qt::NoPen ? qreal(0) : _pen.widthF();
+        if (pw == 0.0)
+            _boundingRect = _path.controlPointRect();
+        else {
+           _boundingRect = _path.controlPointRect();
+        }
+    }
+    return _boundingRect;
+}
+
+QPainterPath GraphicsPathItem::shape() const
+{
+    QPainterPath path;
+    path.addRect(_boundingRect);
+    return qt_graphicsItem_shapeFromPath(path,_pen);
+}
+
+void GraphicsPathItem::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
+{
+
+
+    QPointF local = mapFromScene(point);
+    QString dirName;
+
+    const QRectF &geom = this->boundingRect();
+    QRect delta = this->rect().toRect();
+    switch (dir) {
+    case SizeHandleRect::Right:
+        dirName = "Rigth";
+        delta.setRight(local.x());
+        break;
+    case SizeHandleRect::RightTop:
+        dirName = "RightTop";
+        delta.setTopRight(local.toPoint());
+        break;
+    case SizeHandleRect::RightBottom:
+        dirName = "RightBottom";
+        delta.setBottomRight(local.toPoint());
+        break;
+    case SizeHandleRect::LeftBottom:
+        dirName = "LeftBottom";
+        delta.setBottomLeft(local.toPoint());
+        break;
+    case SizeHandleRect::Bottom:
+        dirName = "Bottom";
+        delta.setBottom(local.y());
+        break;
+    case SizeHandleRect::LeftTop:
+        dirName = "LeftTop";
+        delta.setTopLeft(local.toPoint());
+        break;
+    case SizeHandleRect::Left:
+        dirName = "Left";
+        delta.setLeft(local.x());
+        break;
+    case SizeHandleRect::Top:
+        dirName = "Top";
+        delta.setTop(local.y());
+        break;
+    default:
+        break;
+    }
+
+    prepareGeometryChange();
+    m_width = qAbs(delta.width()) ;
+    m_height = qAbs(delta.height());
+    updateGeometry();
+}
+
+
+
+void GraphicsPathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+
+    QColor c = QColor(Qt::red);
+    c.setAlpha(160);
+    QPen _pen =_pen;
+    _pen.setWidth(4);
+    _pen.setColor(c);
+    painter->setPen(_pen);
+
+    painter->drawPath(_path);
+}

+ 29 - 0
GraphicsPathItem.h

@@ -0,0 +1,29 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsItem.h"
+class GraphicsPathItem : public GraphicsItem
+{
+
+public:
+    GraphicsPathItem(const QPainterPath &painterPath ,GraphicsItem * parent);
+
+    void setPath(QPainterPath path_in)
+    {
+        prepareGeometryChange();
+        //_path = path_in;
+//        _boundingRect =_path.boundingRect();
+        update();
+    }
+    QRectF boundingRect() const;
+    QPainterPath shape() const;
+    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
+    virtual QRectF  rect() const { return QRectF(-m_width / 2 , -m_height / 2 , m_width,m_height) ;}
+protected:
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+protected:
+    qreal m_width;
+    qreal m_height;
+    mutable QRectF _boundingRect;
+    QPainterPath _path;
+};
+

+ 104 - 0
GraphicsPixmapItem.cpp

@@ -0,0 +1,104 @@
+#include "GraphicsPixmapItem.h"
+
+GraphicsPixmapItem::GraphicsPixmapItem(const QPixmap &pixmap ,GraphicsItem *parent)
+    :GraphicsItem(parent)
+    ,m_pixmap(pixmap)
+    ,m_width(pixmap.width())
+    ,m_height(pixmap.height())
+{
+    m_rect =pixmap.rect();
+    m_handles.reserve(SizeHandleRect::None);
+    for (int i = SizeHandleRect::LeftTop; i <= SizeHandleRect::Left; ++i) {
+        SizeHandleRect *shr = new SizeHandleRect(this, static_cast<SizeHandleRect::Direction>(i), this);
+        m_handles.push_back(shr);
+    }
+    updateGeometry();
+    setFlag(QGraphicsItem::ItemIsMovable, true);
+    setFlag(QGraphicsItem::ItemIsSelectable, true);
+    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+    this->setAcceptHoverEvents(true);
+}
+
+
+QRectF GraphicsPixmapItem::boundingRect() const
+{
+    return rect();
+}
+
+QPainterPath GraphicsPixmapItem::shape() const
+{
+    QPainterPath path;
+    path.addRect(boundingRect());
+    return qt_graphicsItem_shapeFromPath(path,_pen);
+}
+
+void GraphicsPixmapItem::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
+{
+    QPointF local = mapFromScene(point);
+    QString dirName;
+
+    QRect delta =m_rect.toRect();
+    switch (dir) {
+    case SizeHandleRect::LeftTop:
+        delta.setTopLeft(local.toPoint());
+        break;
+    case SizeHandleRect::Top:
+        dirName = "Top";
+        delta.setTop(local.y());
+        break;
+
+    case SizeHandleRect::RightTop:
+        dirName = "RightTop";
+        delta.setTopRight(local.toPoint());
+        break;
+
+    case SizeHandleRect::Left:
+        dirName = "Left";
+        delta.setLeft(local.x());
+        break;
+    case SizeHandleRect::Right:
+        dirName = "Rigth";
+        delta.setRight(local.x());
+        break;
+
+    case SizeHandleRect::LeftBottom:
+        dirName = "LeftBottom";
+        delta.setBottomLeft(local.toPoint());
+        break;
+
+    case SizeHandleRect::Bottom:
+        dirName = "Bottom";
+        delta.setBottom(local.y());
+        break;
+
+    case SizeHandleRect::RightBottom:
+        dirName = "RightBottom";
+        delta.setBottomRight(local.toPoint());
+        break;
+
+    default:
+        break;
+    }
+
+
+    prepareGeometryChange();
+
+    m_width = delta.width();
+    m_height = delta.height();
+    m_rect =delta;
+    updateGeometry();
+}
+
+
+
+void GraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    qreal x =rect().left();
+    if(rect().left() >rect().right())
+        x =rect().right();
+    qreal y =rect().top();
+    if(rect().top() >rect().bottom())
+        y =rect().bottom();
+    painter->drawPixmap(x,y,m_pixmap.scaled(abs(rect().width()),abs(rect().height()),
+                                                                   Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
+}

+ 30 - 0
GraphicsPixmapItem.h

@@ -0,0 +1,30 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsItem.h"
+class GraphicsPixmapItem : public GraphicsItem
+{
+public:
+    GraphicsPixmapItem(const QPixmap &pixmap ,GraphicsItem * parent);
+
+    QRectF boundingRect() const;
+    QPainterPath shape() const;
+    void resetShape()
+    {
+        m_rect.setLeft(0);
+        m_rect.setTop(0);
+        m_rect.setWidth(abs(m_width));
+        m_rect.setHeight(abs(m_height));
+        updateGeometry();
+    }
+    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
+    virtual QRectF  rect() const {
+        return
+                QRectF( QPointF(m_rect.left(),m_rect.top()),
+                        QPointF(m_rect.right(), m_rect.bottom())) ;}protected:
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+protected:
+    qreal m_width;
+    qreal m_height;
+    QPixmap m_pixmap;
+};

+ 103 - 0
GraphicsRectItem.cpp

@@ -0,0 +1,103 @@
+#include "GraphicsRectItem.h"
+
+GraphicsRectItem::GraphicsRectItem(const QRect & rect ,QGraphicsItem *parent)
+    :GraphicsItem(parent)
+    ,m_width(rect.width())
+    ,m_height(rect.height())
+    ,m_isSquare(false)
+{
+
+    m_rect =rect;
+    m_handles.reserve(SizeHandleRect::None);
+    for (int i = SizeHandleRect::LeftTop; i <= SizeHandleRect::Left; ++i) {
+        SizeHandleRect *shr = new SizeHandleRect(this, static_cast<SizeHandleRect::Direction>(i), this);
+        m_handles.push_back(shr);
+    }
+    updateGeometry();
+    setFlag(QGraphicsItem::ItemIsMovable, true);
+    setFlag(QGraphicsItem::ItemIsSelectable, true);
+    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+    this->setAcceptHoverEvents(true);
+}
+
+QRectF GraphicsRectItem::boundingRect() const
+{
+    return rect();
+}
+
+QPainterPath GraphicsRectItem::shape() const
+{
+    QPainterPath path;
+    path.addRect(boundingRect());
+    return qt_graphicsItem_shapeFromPath(path,_pen);
+}
+
+void GraphicsRectItem::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
+{
+    QPointF local = mapFromScene(point);
+    QString dirName;
+
+    QRect delta =m_rect.toRect();
+    switch (dir) {
+    case SizeHandleRect::LeftTop:
+        delta.setTopLeft(local.toPoint());
+
+        break;
+    case SizeHandleRect::Top:
+        dirName = "Top";
+        delta.setTop(local.y());
+        break;
+
+    case SizeHandleRect::RightTop:
+        dirName = "RightTop";
+        delta.setTopRight(local.toPoint());
+        break;
+
+    case SizeHandleRect::Left:
+        dirName = "Left";
+        delta.setLeft(local.x());
+        break;
+    case SizeHandleRect::Right:
+        dirName = "Rigth";
+        delta.setRight(local.x());
+        break;
+
+    case SizeHandleRect::LeftBottom:
+        dirName = "LeftBottom";
+        delta.setBottomLeft(local.toPoint());
+        break;
+
+    case SizeHandleRect::Bottom:
+        dirName = "Bottom";
+        delta.setBottom(local.y());
+        break;
+
+    case SizeHandleRect::RightBottom:
+        dirName = "RightBottom";
+        delta.setBottomRight(local.toPoint());
+        break;
+
+    default:
+        break;
+    }
+    prepareGeometryChange();
+    if(m_isSquare)
+    {
+        delta.setHeight(delta.width());
+    }
+    m_width = delta.width();
+    m_height = delta.height();
+    m_rect =delta;
+    updateGeometry();
+}
+
+
+
+void GraphicsRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    QPen pen =painter->pen();
+    pen.setWidth(4);
+    pen.setColor(m_color);
+    painter->setPen(pen);
+    painter->drawRect(rect());
+}

+ 44 - 0
GraphicsRectItem.h

@@ -0,0 +1,44 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsItem.h"
+class GraphicsRectItem : public GraphicsItem
+{
+public:
+    GraphicsRectItem(const QRect & rect ,QGraphicsItem * parent);
+
+    QRectF boundingRect() const;
+    QPainterPath shape() const;
+    void resetShape()
+    {
+        m_rect.setLeft(0);
+        m_rect.setTop(0);
+        m_rect.setWidth(abs(m_width));
+        m_rect.setHeight(abs(m_height));
+        updateGeometry();
+    }
+
+    void setBorderColor(QColor color)
+    {
+        m_color =color;
+    }
+    void setIsSquare()
+    {
+        m_isSquare =true;
+    }
+    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
+    virtual QRectF  rect() const {
+        return
+                QRectF( QPointF(m_rect.left(),m_rect.top()),
+                        QPointF(m_rect.right(), m_rect.bottom())) ;}
+
+protected:
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+protected:
+    qreal m_width;
+    qreal m_height;
+    bool m_isSquare; //是否为正方形
+    QColor m_color;
+
+
+
+};

+ 40 - 0
GraphicsTextItem.cpp

@@ -0,0 +1,40 @@
+#include "GraphicsTextItem.h"
+#include <QDebug>
+
+
+GraphicsTextItem::GraphicsTextItem(QGraphicsItem *parent)
+    : QGraphicsTextItem(parent)
+{
+    setFlag(QGraphicsItem::ItemIsMovable);
+    setFlag(QGraphicsItem::ItemIsSelectable);
+    setFlag(QGraphicsItem::ItemIsFocusable );
+    setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+}
+//! [0]
+
+//! [1]
+QVariant GraphicsTextItem::itemChange(GraphicsItemChange change,
+                                      const QVariant &value)
+{
+    if (change == QGraphicsItem::ItemSelectedHasChanged)
+        emit selectedChange(this);
+    return value;
+}
+//! [1]
+
+//! [2]
+void GraphicsTextItem::focusOutEvent(QFocusEvent *event)
+{
+    setTextInteractionFlags(Qt::NoTextInteraction);
+    // emit lostFocus(this);
+    QGraphicsTextItem::focusOutEvent(event);
+}
+//! [2]
+
+//! [5]
+void GraphicsTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
+{
+    if (textInteractionFlags() == Qt::NoTextInteraction)
+        setTextInteractionFlags(Qt::TextEditorInteraction);
+    QGraphicsTextItem::mouseDoubleClickEvent(event);
+}

+ 24 - 0
GraphicsTextItem.h

@@ -0,0 +1,24 @@
+#pragma once
+#include "preheader.h"
+
+class GraphicsTextItem : public QGraphicsTextItem
+{
+    Q_OBJECT
+
+public:
+    enum { Type = UserType + 3 };
+
+    GraphicsTextItem(QGraphicsItem *parent = 0);
+
+    int type() const override { return Type; }
+
+signals:
+    void lostFocus(GraphicsTextItem *item);
+    void selectedChange(QGraphicsItem *item);
+
+protected:
+    QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
+    void focusOutEvent(QFocusEvent *event) override;
+    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
+
+};

+ 35 - 0
GraphicsTriangleItem.cpp

@@ -0,0 +1,35 @@
+#include "GraphicsTriangleItem.h"
+
+GraphicsTriangleItem::GraphicsTriangleItem(const QRect &rect, QGraphicsItem *parent)
+    :GraphicsRectItem(rect,parent)
+{
+}
+
+QPainterPath GraphicsTriangleItem::shape() const
+{
+    QPainterPath path;
+    QRectF rc = rect();
+    QPointF middle =QPointF((rc.left() + rc.right())*0.5,0);
+
+    QPolygonF item;
+    item <<rc.bottomLeft()<<middle<< rc.bottomRight()<<rc.bottomLeft();
+    path.addPolygon(item);
+    return qt_graphicsItem_shapeFromPath(path,_pen);
+}
+
+void GraphicsTriangleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    QRectF rc = rect();
+
+    QPointF middle =QPointF((rc.left() + rc.right())*0.5,0);
+
+    QPolygonF item;
+    item <<rc.bottomLeft()<<middle<< rc.bottomRight()<<rc.bottomLeft();
+    QPen pen =painter->pen();
+    pen.setWidth(4);
+    pen.setColor(m_color);
+    painter->setPen(pen);
+    painter->drawPolygon(item);
+
+}
+

+ 13 - 0
GraphicsTriangleItem.h

@@ -0,0 +1,13 @@
+#pragma once
+#include "preheader.h"
+#include "GraphicsRectItem.h"
+class GraphicsTriangleItem : public GraphicsRectItem
+{
+public:
+    GraphicsTriangleItem(const QRect & rect ,QGraphicsItem * parent);
+    QPainterPath shape() const;
+
+
+protected:
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+};

+ 217 - 0
ImageEdit.cpp

@@ -0,0 +1,217 @@
+#include "ImageEdit.h"
+#include "ui_ImageEdit.h"
+
+ImageEdit::ImageEdit(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::ImageEdit)
+{
+
+    ui->setupUi(this);
+    //使用UI设计的Actions设计工具栏
+    QToolBar* locToolBar = new QToolBar(tr("图片"),this); //创建工具栏
+    locToolBar->addAction(ui->openAction);
+    connect (ui->openAction,SIGNAL(triggered(bool)),this,SLOT(imageOpen()));
+    locToolBar->addAction(ui->saveAction);
+    connect (ui->saveAction,SIGNAL(triggered(bool)),this,SLOT(imageSave()));
+    locToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    QVBoxLayout *Layout = new QVBoxLayout();//图片合成主界面垂直布局
+    Layout->addWidget(locToolBar); //设置工具栏和编辑器上下布局
+    _mainPaintScene =new MainPaintScene( ui->graphicsView);
+    ui->graphicsView->setScene(_mainPaintScene);
+    ui->graphicsView->centerOn(0,0);
+
+//    qDebug()<<ui->graphicsView->width()*0.5<<ui->graphicsView->height()*0.5;
+
+    connect(this, SIGNAL(changeCurrentShape(DrawBaseShape)),
+            _mainPaintScene, SLOT(SetCurrentShape(DrawBaseShape)));
+    initToolBar();
+}
+
+ImageEdit::~ImageEdit()
+{
+    SafeDelete(_mainPaintScene);
+    delete ui;
+}
+void ImageEdit::initToolBar()
+{
+    ui->pbt_Green->hide();
+    ui->pbt_Blue->hide();
+    //    ui->pbt_line->hide();
+    ui->pbt_circle->hide();
+    ui->pbt_triangle->hide();
+
+}
+
+void ImageEdit:: resizeEvent(QResizeEvent *event)
+{
+
+    ui->graphicsView->resize(width() -ui->rightWgt->width() ,
+                             height());
+    ui->graphicsView->move(0,0);
+
+    ui->rightWgt->resize(ui->rightWgt->width(),height());
+    ui->rightWgt->move(width()-ui->rightWgt->width(),0);
+
+    //    ui->control_bar->move( 0.5 *(width()-ui->rightWgt->width()- ui->control_bar->width())
+    //                           ,height()-1.4* ui->control_bar->height());
+
+}
+//笔形绘制
+void ImageEdit::on_pushButton_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::penPath);
+    QPixmap pixmap(":/new/prefix1/images/ic_sidebar_pencil.png");
+    //定义大小
+    QSize picSize(8, 8);
+    //缩放图片,按比例
+    QPixmap scaledPixmap = pixmap.scaled(picSize, Qt::KeepAspectRatio);
+    //设置样式
+    QCursor cursor(scaledPixmap, -1, -1);
+    //更改鼠标形状
+    this->setCursor(cursor);
+}
+
+//文本绘制
+void ImageEdit::on_pushButton_2_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::text);
+}
+
+//选择图元
+void ImageEdit::on_pushButton_4_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::selection);
+}
+
+
+//图片
+void ImageEdit::on_pushButton_5_clicked()
+{
+    QString fileDir = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Images (*.png *.xpm *.jpg)"));
+
+    qDebug() << "file Dir ==== "<<fileDir;
+    _mainPaintScene->InsertPicture(fileDir);
+
+    emit changeCurrentShape(DrawBaseShape::image);
+}
+
+
+void ImageEdit::on_pushButton_9_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::rotation);
+}
+
+
+
+void ImageEdit::on_pushButton_Color_clicked()
+{
+    _mainPaintScene->setCurrentColor(QColor(255,88,80,255)); //红色
+}
+void ImageEdit::onSetColor(QColor color)
+{
+
+}
+
+void ImageEdit::on_pushButton_6_clicked()
+{
+    initToolBar();
+    ui->pbt_Green->show();
+    ui->pbt_Blue->show();
+}
+
+void ImageEdit::on_pushButton_3_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::arrowLine);
+}
+
+void ImageEdit::on_pushButton_8_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::selection);
+}
+
+//void ImageEdit::on_pushButton_7_clicked()
+//{
+//    emit changeCurrentShape(DrawBaseShape::line);
+//}
+
+void ImageEdit::on_pushButton_12_clicked()
+{
+    initToolBar(); //将所有该隐藏的按钮隐藏;
+    ui->pbt_line->show();
+}
+
+void ImageEdit::on_pushButton_13_clicked()
+{
+    initToolBar(); //将所有该隐藏的按钮隐藏;
+    ui->pbt_circle->show();
+    ui->pbt_triangle->show();
+
+}
+
+void ImageEdit::on_pbt_line_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::line);
+}
+
+void ImageEdit::on_pbt_Rect_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::rectangle);
+}
+
+void ImageEdit::on_pbt_triangle_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::triangle);
+}
+
+void ImageEdit::on_pbt_circle_clicked()
+{
+    emit changeCurrentShape(DrawBaseShape::ellipse);
+}
+void ImageEdit::on_pbt_Blue_clicked()
+{
+    _mainPaintScene->setCurrentColor(QColor(55,164,245,255)); //蓝色
+}
+
+void ImageEdit::on_pbt_Green_clicked()
+{
+    _mainPaintScene->setCurrentColor(QColor(29,185,84,255)); //绿色
+}
+
+//void ImageEdit::on_pbt_prePage_clicked()
+//{
+//    QString fileDir = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Images (*.png *.xpm *.jpg)"));
+
+//    _mainPaintScene->SetBackGroundImage(fileDir);
+//}
+
+
+
+/**
+ * @brief ImageEdit::imageSave 保存图片
+ */
+void ImageEdit::imageSave()
+{
+    QString filename1 = QFileDialog::getSaveFileName(this,tr("保存图片"),"",tr("Images (*.jpg)")); //选择路径
+    //    QPixmap pixmap(_mainPaintScene->sceneRect().width(),1378);
+    QPixmap pixmap(_mainPaintScene->sceneRect().width(),_mainPaintScene->sceneRect().height());
+    //    QPixmap fitpixmap = pixmap.scaled(1083, 1378, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 饱满填充
+    pixmap.fill(Qt::white);
+    qDebug()<<_mainPaintScene->sceneRect().width()<<_mainPaintScene->sceneRect().height();
+    qDebug()<<_mainPaintScene->width()<<_mainPaintScene->height();
+    QPainter painter(&pixmap);
+    //    QPainter painter(&image);
+    _mainPaintScene->render(&painter);   //关键函数
+    pixmap.save(filename1, "JPG");
+
+}
+
+/**
+ * @brief ImageEdit::imageopen 打开图片
+ */
+void ImageEdit::imageOpen()
+{
+    QString fileDir = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Images (*.png *.xpm *.jpg)"));
+
+    _mainPaintScene->SetBackGroundImage(fileDir);
+}
+

+ 74 - 0
ImageEdit.h

@@ -0,0 +1,74 @@
+#pragma once
+#include "preheader.h"
+#include "PaintView.h"
+#include "MainPaintScenee.h"
+
+namespace Ui {
+class ImageEdit;
+}
+
+class ImageEdit : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit ImageEdit(QWidget *parent = 0);
+    ~ImageEdit();
+
+private slots:
+    void on_pushButton_clicked();
+    void on_pushButton_2_clicked();
+
+    void on_pushButton_4_clicked();
+
+
+    void on_pushButton_5_clicked();
+
+    void on_pushButton_9_clicked();
+
+    void on_pushButton_Color_clicked();
+    void onSetColor(QColor color);
+
+    void on_pushButton_6_clicked();
+
+    void on_pushButton_3_clicked();
+
+    void on_pushButton_8_clicked();
+
+    //    void on_pushButton_7_clicked();
+
+    void on_pushButton_12_clicked();
+
+
+
+    void on_pushButton_13_clicked();
+
+    void on_pbt_line_clicked();
+
+    void on_pbt_Rect_clicked();
+
+    void on_pbt_triangle_clicked();
+
+    void on_pbt_circle_clicked();
+
+    void on_pbt_Blue_clicked();
+
+    void on_pbt_Green_clicked();
+
+//    void on_pbt_prePage_clicked();
+
+    void imageSave();//保存图片
+
+    void imageOpen();//打开图片
+
+
+signals:
+    void changeCurrentShape(DrawBaseShape shape);
+private:
+    Ui::ImageEdit *ui;
+    MainPaintScene *_mainPaintScene;
+
+    void initToolBar();//将所有该隐藏的按钮隐藏;
+    void resizeEvent(QResizeEvent *event);
+};
+

+ 784 - 0
ImageEdit.ui

@@ -0,0 +1,784 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ImageEdit</class>
+ <widget class="QWidget" name="ImageEdit">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>848</width>
+    <height>663</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>848</width>
+    <height>663</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="styleSheet">
+   <string notr="true">border: 1px solid #6D6D6E;</string>
+  </property>
+  <widget class="QWidget" name="rightWgt" native="true">
+   <property name="geometry">
+    <rect>
+     <x>792</x>
+     <y>9</y>
+     <width>47</width>
+     <height>645</height>
+    </rect>
+   </property>
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+   <property name="minimumSize">
+    <size>
+     <width>47</width>
+     <height>0</height>
+    </size>
+   </property>
+   <property name="maximumSize">
+    <size>
+     <width>47</width>
+     <height>16777215</height>
+    </size>
+   </property>
+   <property name="styleSheet">
+    <string notr="true">background: #808080;
+background: rgba(0,0,0,0.50);
+border: 1px solid #6D6D6E;</string>
+   </property>
+   <layout class="QVBoxLayout" name="verticalLayout">
+    <property name="spacing">
+     <number>0</number>
+    </property>
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
+     <number>0</number>
+    </property>
+    <item>
+     <widget class="QPushButton" name="pushButton">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_pencil.png</normaloff>:/new/prefix1/images/ic_sidebar_pencil.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_2">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_text.png</normaloff>:/new/prefix1/images/ic_sidebar_text.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_3">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_arrow.png</normaloff>:/new/prefix1/images/ic_sidebar_arrow.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_12">
+      <property name="minimumSize">
+       <size>
+        <width>0</width>
+        <height>8</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>16777215</width>
+        <height>8</height>
+       </size>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">color: rgb(255, 255, 255);</string>
+      </property>
+      <property name="text">
+       <string>▼▼▼</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pbt_line">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">font: 14pt &quot;Agency FB&quot;;</string>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_drawing_beeline.png</normaloff>:/new/prefix1/images/ic_drawing_beeline.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pbt_Rect">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_shape.png</normaloff>:/new/prefix1/images/ic_sidebar_shape.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_13">
+      <property name="minimumSize">
+       <size>
+        <width>0</width>
+        <height>8</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>16777215</width>
+        <height>8</height>
+       </size>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">color: rgb(255, 255, 255);</string>
+      </property>
+      <property name="text">
+       <string>▼▼▼</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pbt_triangle">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_drawing_triangle.png</normaloff>:/new/prefix1/images/ic_drawing_triangle.png</iconset>
+      </property>
+      <property name="iconSize">
+       <size>
+        <width>16</width>
+        <height>16</height>
+       </size>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pbt_circle">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_drawing_round.png</normaloff>:/new/prefix1/images/ic_drawing_round.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_8">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_checked.png</normaloff>:/new/prefix1/images/ic_sidebar_checked.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_5">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_image.png</normaloff>:/new/prefix1/images/ic_sidebar_image.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_Color">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_sidebar_color.png</normaloff>:/new/prefix1/images/ic_sidebar_color.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pbt_Blue">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">background: #37A4F5; 
+border-bottom-color: rgb(138, 80, 255);
+gridline-color: rgb(0, 0, 0);
+border-width: 9px;  
+border-color: rgb(106, 106, 106);</string>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer name="verticalSpacer_2">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeType">
+       <enum>QSizePolicy::Maximum</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>20</width>
+        <height>1</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pbt_Green">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">background: #1DB954;
+border-bottom-color: rgb(138, 80, 255);
+gridline-color: rgb(0, 0, 0);
+border-width: 9px;  
+border-color: rgb(106, 106, 106);</string>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_6">
+      <property name="minimumSize">
+       <size>
+        <width>0</width>
+        <height>8</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>16777215</width>
+        <height>8</height>
+       </size>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">color: rgb(255, 255, 255);</string>
+      </property>
+      <property name="text">
+       <string>▼▼▼</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_4">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="palette">
+       <palette>
+        <active>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="PlaceholderText">
+          <brush brushstyle="NoBrush">
+           <color alpha="128">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </active>
+        <inactive>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="PlaceholderText">
+          <brush brushstyle="NoBrush">
+           <color alpha="128">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </inactive>
+        <disabled>
+         <colorrole role="WindowText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Button">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Text">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="ButtonText">
+          <brush brushstyle="SolidPattern">
+           <color alpha="255">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Base">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="Window">
+          <brush brushstyle="SolidPattern">
+           <color alpha="127">
+            <red>0</red>
+            <green>0</green>
+            <blue>0</blue>
+           </color>
+          </brush>
+         </colorrole>
+         <colorrole role="PlaceholderText">
+          <brush brushstyle="NoBrush">
+           <color alpha="128">
+            <red>255</red>
+            <green>255</green>
+            <blue>255</blue>
+           </color>
+          </brush>
+         </colorrole>
+        </disabled>
+       </palette>
+      </property>
+      <property name="font">
+       <font>
+        <pointsize>10</pointsize>
+        <weight>75</weight>
+        <bold>true</bold>
+       </font>
+      </property>
+      <property name="styleSheet">
+       <string notr="true">color: rgb(255, 255, 255);</string>
+      </property>
+      <property name="text">
+       <string>选择</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButton_9">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_turn left.png</normaloff>:/new/prefix1/images/ic_turn left.png</iconset>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QToolButton" name="toolButton_10">
+      <property name="minimumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="maximumSize">
+       <size>
+        <width>47</width>
+        <height>47</height>
+       </size>
+      </property>
+      <property name="text">
+       <string/>
+      </property>
+      <property name="icon">
+       <iconset resource="qrc.qrc">
+        <normaloff>:/new/prefix1/images/ic_turn right.png</normaloff>:/new/prefix1/images/ic_turn right.png</iconset>
+      </property>
+      <property name="popupMode">
+       <enum>QToolButton::MenuButtonPopup</enum>
+      </property>
+      <property name="arrowType">
+       <enum>Qt::UpArrow</enum>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer name="verticalSpacer">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>47</width>
+        <height>40</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+   </layout>
+  </widget>
+  <widget class="PaintView" name="graphicsView">
+   <property name="geometry">
+    <rect>
+     <x>10</x>
+     <y>10</y>
+     <width>781</width>
+     <height>641</height>
+    </rect>
+   </property>
+  </widget>
+  <action name="saveAction">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/save.png</normaloff>:/new/prefix1/images/save.png</iconset>
+   </property>
+   <property name="text">
+    <string>保存</string>
+   </property>
+  </action>
+  <action name="openAction">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/open.ico</normaloff>:/new/prefix1/images/open.ico</iconset>
+   </property>
+   <property name="text">
+    <string>打开</string>
+   </property>
+   <property name="toolTip">
+    <string>打开</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>PaintView</class>
+   <extends>QGraphicsView</extends>
+   <header location="global">../GradeSystem/UI/GradeGraphics/PaintView.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="qrc.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 189 - 0
MainPaintScene.cpp

@@ -0,0 +1,189 @@
+#include "MainPaintScenee.h"
+#include<QGraphicsSceneMouseEvent>
+#include<QGraphicsRectItem>
+#include <QDebug>
+
+const double initWidth =700.0;
+const double initHeight =663.0;
+MainPaintScene::MainPaintScene(QObject *parent) :
+    QGraphicsScene(parent)
+{
+    //    QRect mainRect(0,0,2000,2000);
+    //    setSceneRect(mainRect);//设置场景范围
+    //    addRect(mainRect,QPen(Qt::black));//把场景范围直观显示出来,只为了方便理解
+
+    //    _colorBak=Qt::red;
+
+}
+
+MainPaintScene::~MainPaintScene()
+{
+    SafeDelete (textItem);
+}
+void MainPaintScene::InsertPicture(QString path)
+{
+    DrawTool * tool =DrawTool::findTool(image);
+    if (tool)
+    {
+        tool->setPicture(path);
+    }
+}
+
+void MainPaintScene::mouseEvent(QGraphicsSceneMouseEvent *mouseEvent)
+{
+    switch( mouseEvent->type() ){
+    case QEvent::GraphicsSceneMousePress:
+        QGraphicsScene::mousePressEvent(mouseEvent);
+        break;
+    case QEvent::GraphicsSceneMouseMove:
+        QGraphicsScene::mouseMoveEvent(mouseEvent);
+        break;
+    case QEvent::GraphicsSceneMouseRelease:
+        QGraphicsScene::mouseReleaseEvent(mouseEvent);
+        break;
+    }
+}
+
+//打开文件
+void MainPaintScene::SetBackGroundImage(QString path)
+{
+    this->clear();
+    //this->addRect(0,0,initWidth,initHeight,QPen(Qt::green),QBrush(Qt::red));
+    QPixmap pixmap =QPixmap::fromImage(QImage(path));
+    double dpiX = QApplication::desktop()->physicalDpiX();
+    double dpiY = QApplication::desktop()->physicalDpiY();
+    int physicalX=(int)(dpiX*5.5/2.54+0.5f);
+    int physicalY=(int)(dpiY*7/2.54+0.5f);
+    QPixmap fitpixmap = pixmap.scaled(physicalX, physicalY, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 饱满填充
+//    QPixmap fitpixmap = pixmap.scaled(1083, 1378, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 饱满填充
+    QGraphicsPixmapItem* _backGroundItem= this->addPixmap(fitpixmap);
+
+    //    if(pixmap.width()>pixmap.height())
+    //    {
+    //        //匹配宽度
+    //        _backGroundItem->setScale( initWidth/pixmap.width() );
+    //    }
+    //    else//匹配高度
+    //    {
+    //        _backGroundItem->setScale( initHeight /pixmap.height() );
+    //    }
+    _backGroundItem->setPos(0,0);
+
+}
+
+void MainPaintScene::keyPressEvent(QKeyEvent *event)
+{
+    //    DrawTool * tool =DrawTool::findTool( DrawTool::c_drawShape );
+    //    if (tool)
+    //        tool->keyPressEvent(event,this);
+    QList<QGraphicsItem *> selectItems =  selectedItems();
+    switch (event->key())
+    {
+    case Qt::Key_Delete:
+        if(selectItems.count()>0)
+        {
+            while(selectItems.count()>0)
+            {
+                QGraphicsItem * item =selectItems.last();
+                removeItem(item);
+                selectItems.pop_back();
+            }
+        }
+        break;
+    default:
+        break;
+    }
+    QGraphicsScene::keyPressEvent(event);
+
+
+}
+
+void MainPaintScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
+{
+    DrawTool * tool =DrawTool::findTool( DrawTool::c_drawShape );
+    if( DrawTool::c_drawShape  ==text) //文字独立出来
+    {
+        textItem = new GraphicsTextItem();
+
+        QFont myFont =textItem->font();
+        myFont.setWeight(QFont::Bold);
+        myFont.setFamily("SimSun");
+        myFont.setPixelSize(24);
+
+        textItem->setDefaultTextColor(_color);
+        textItem->setFont(myFont);
+        textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
+        textItem->setZValue(1000.0);
+        connect(textItem, SIGNAL(lostFocus(GraphicsTextItem*)),
+                this, SLOT(editorLostFocus(GraphicsTextItem*)));
+        connect(textItem, SIGNAL(selectedChange(GraphicsTextItem*)),
+                this, SIGNAL(itemSelected(GraphicsTextItem*)));
+        addItem(textItem);
+        textItem->setDefaultTextColor(Qt::red);
+        textItem->setPos(mouseEvent->scenePos());
+        textItem->setFlag(QGraphicsItem::ItemIsMovable);
+        textItem->setAcceptDrops(true);
+        SetCurrentShape(selection);
+    }
+    else if (tool)
+    {
+        tool->mousePressEvent(mouseEvent,this);
+    }
+
+}
+void MainPaintScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
+{
+    DrawTool * tool = DrawTool::findTool( DrawTool::c_drawShape );
+    if( DrawTool::c_drawShape  ==text) //文字独立出来
+    {
+        QGraphicsScene::mouseMoveEvent(mouseEvent);
+    }
+    else if(tool)
+        tool->mouseMoveEvent(mouseEvent,this);
+
+
+}
+
+void MainPaintScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
+{
+    DrawTool * tool =DrawTool::findTool( DrawTool::c_drawShape );
+    if( DrawTool::c_drawShape  ==text) //文字独立出来
+    {
+
+    }
+    else if ( tool )
+        tool->mouseReleaseEvent(mouseEvent,this);
+}
+void MainPaintScene::setCurrentColor(QColor color)
+{
+    DrawTool * tool =DrawTool::findTool( DrawTool::c_drawShape );
+    if ( tool )
+        tool->setCurrentColor(color);
+    _color =color;
+}
+void MainPaintScene::SetCurrentShape(DrawBaseShape shape)
+{
+    if ( shape == selection)
+        DrawTool::c_drawShape = selection;
+    if ( shape == rotation)
+        DrawTool::c_drawShape = rotation;
+    if ( shape == line)
+        DrawTool::c_drawShape = line;
+    if ( shape == rectangle)
+        DrawTool::c_drawShape = rectangle;
+    if ( shape == ellipse)
+        DrawTool::c_drawShape = ellipse;
+    if ( shape == penPath)
+        DrawTool::c_drawShape = penPath;
+    if ( shape == text)
+        DrawTool::c_drawShape = text;
+    if ( shape == image)
+        DrawTool::c_drawShape = image;
+    if ( shape == arrowLine)
+        DrawTool::c_drawShape = arrowLine;
+    if ( shape == triangle)
+        DrawTool::c_drawShape = triangle;
+    DrawTool * tool =DrawTool::findTool( DrawTool::c_drawShape );
+    if ( tool )
+        tool->setCurrentColor(_color);
+}

+ 61 - 0
MainPaintScenee.h

@@ -0,0 +1,61 @@
+#ifndef MAINPAINTSCENEE_H
+#define MAINPAINTSCENEE_H
+
+#include <QGraphicsScene>
+
+QT_BEGIN_NAMESPACE
+class QGraphicsSceneMouseEvent;
+class QMenu;
+class QPointF;
+class QFont;
+class QColor;
+QT_END_NAMESPACE
+#include "drawtool.h"
+#include "GraphicsTextItem.h"
+#include "GraphicsLineItem.h"
+
+class DrawTool;
+
+class MainPaintScene : public QGraphicsScene
+{
+    Q_OBJECT
+
+public:
+    explicit MainPaintScene(QObject *parent = 0);
+    ~MainPaintScene();
+
+    void mouseEvent(QGraphicsSceneMouseEvent *mouseEvent );
+    void InsertPicture(QString path);
+    void SetBackGroundImage(QString path);
+
+    void setCurrentColor(QColor);
+public slots:
+    void SetCurrentShape(DrawBaseShape shape);
+    void editorLostFocus(GraphicsTextItem *item)
+    {
+        QTextCursor cursor = item->textCursor();
+        cursor.clearSelection();
+        item->setTextCursor(cursor);
+
+        if (item->toPlainText().isEmpty()) {
+            removeItem(item);
+            item->deleteLater();
+        }
+    }
+
+signals:
+    void itemSelected(QGraphicsItem *item);
+    void textInserted(GraphicsTextItem *item);
+
+private:
+    void keyPressEvent(QKeyEvent *event);
+    void mousePressEvent(QGraphicsSceneMouseEvent *event);
+    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+
+    QColor _color=QColor(255,88,80,255);
+    GraphicsTextItem *textItem=nullptr;
+};
+
+#endif // MAINPAINTSCENEE_H

+ 365 - 0
PaintView.cpp

@@ -0,0 +1,365 @@
+#include "PaintView.h"
+#define VIEW_CENTER viewport()->rect().center()
+#define VIEW_WIDTH  viewport()->rect().width()
+#define VIEW_HEIGHT viewport()->rect().height()
+PaintView::PaintView(QWidget *parent) :
+    QGraphicsView(parent)
+{
+    _zoomDelta=0.1;  // 缩放的增量
+    _scaleValue=1.0;
+    _bMouseTranslate=false;
+    _translateSpeed=1.0;
+
+    this->setRenderHint(QPainter::Antialiasing);
+
+
+}
+
+PaintView::~PaintView()
+{
+
+}
+void PaintView::ZoomIn()
+{
+    zoom(1 + _zoomDelta);
+}
+
+// 缩小
+void PaintView::ZoomOut()
+{
+    zoom(1 - _zoomDelta);
+}
+void PaintView::zoom(float scaleFactor)
+{
+    // 防止过小或过大
+    qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
+    if (factor < 0.07 || factor > 100)
+        return;
+
+    scale(scaleFactor, scaleFactor);
+    _scaleValue *= scaleFactor;
+}
+
+void PaintView::wheelEvent(QWheelEvent *event)
+{
+    // 滚轮的滚动量
+    QPoint scrollAmount = event->angleDelta();
+    // 正值表示滚轮远离使用者(放大),负值表示朝向使用者(缩小)
+    scrollAmount.y() > 0 ? ZoomIn() :ZoomOut();
+}
+
+void  PaintView::paintEvent(QPaintEvent *event)
+{
+    QGraphicsView::paintEvent(event);
+    QPainter painter(this->viewport());
+    painter.setBrush(Qt::gray);
+    QFont font;
+    font.setPixelSize(45);
+    painter.setFont(font);
+//    painter.drawb(QRectF(width()*0.3,height()*0.2,width()*0.3,height()*0.3),"made by andy!");
+
+}
+// 平移
+void PaintView::mouseMoveEvent(QMouseEvent *event)
+{
+    if (_bMouseTranslate){
+        QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(_lastMousePos);
+        translate(mouseDelta);
+    }
+
+    _lastMousePos = event->pos();
+
+    QGraphicsView::mouseMoveEvent(event);
+}
+
+void PaintView::mousePressEvent(QMouseEvent *event)
+{
+    if (event->button() == _translateButton) {
+        // 当光标底下没有 item 时,才能移动
+        QPointF point = mapToScene(event->pos());
+        if (scene()->itemAt(point, transform()) == NULL)  {
+            _bMouseTranslate = true;
+            _lastMousePos = event->pos();
+        }
+    }
+
+    QGraphicsView::mousePressEvent(event);
+}
+
+void PaintView::onAssemblageAction(bool)
+{
+    QList<QGraphicsItem *>  selectItems=this->scene()->selectedItems();
+    QGraphicsItemGroup * groupItems =this->scene()->createItemGroup(selectItems);
+    QRectF rect =groupItems->boundingRect();
+
+    QGraphicsScene  *scene =new QGraphicsScene();
+    scene->setSceneRect(rect);
+    for(int i=0; i<selectItems.count(); i++)
+    {
+        QGraphicsItem *sp = qgraphicsitem_cast<QGraphicsItem*>(selectItems[i]);
+        scene->addItem(sp);
+    }
+    scene->clearSelection();
+    QImage image(rect.width(),rect.height(),QImage::Format_ARGB32);
+    image.fill(Qt::transparent);//用透明色填充
+    QString pngName = "D:/scene44test.png";
+    QPainter painter(&image);
+    painter.setRenderHint(QPainter::Antialiasing);
+    scene->render(&painter);
+    bool saveSuccess =  image.save(pngName);
+    
+    for(int i=0; i<selectItems.count(); i++)
+    {
+        QGraphicsItem *sp = qgraphicsitem_cast<QGraphicsItem*>(selectItems[i]);
+        this->scene()->addItem(sp);
+    }
+    if (!saveSuccess)
+    {
+        QMessageBox::about(NULL,"","组合图元失败!");
+    }
+    else
+        QMessageBox::about(NULL,"","组合图元成功!");
+
+    SafeDelete(scene);
+}
+void PaintView::onRotation1Action(bool)
+{
+    QList< QGraphicsItem*>  selectItems=this->scene()->selectedItems();
+    int selectItemsCount =selectItems.count();
+
+    for(int i=0; i<selectItemsCount ;i++)
+    {
+        //图元自转
+        QPointF centerPos=  selectItems[i]->boundingRect().center() ;
+        selectItems[i]->setTransformOriginPoint(centerPos);
+        selectItems[i]->setRotation(selectItems[i]->rotation()+30);
+    }
+}
+void PaintView::onRotation2Action(bool)
+{
+    QList<QGraphicsItem *>  selectItems=this->scene()->selectedItems();
+    int selectItemsCount =selectItems.count();
+
+    for(int i=0; i<selectItemsCount ;i++)
+    {
+        //图元自转
+        QPointF centerPos=  selectItems[i]->boundingRect().center() ;
+        selectItems[i]->setTransformOriginPoint(centerPos);
+        selectItems[i]->setRotation(selectItems[i]->rotation()-30);
+    }
+}
+void PaintView::onDeleteAction(bool)
+{
+    QList<QGraphicsItem *>  selectItems=this->scene()->selectedItems();
+    int selectItemsCount =selectItems.count();
+
+
+    for(int i=0; i<selectItemsCount ;i++)
+    {
+        this->scene()->removeItem(selectItems[i]);
+    }
+}
+void PaintView::contextMenuEvent(QContextMenuEvent *event)
+{
+    QList<QGraphicsItem *>  selectItems=this->scene()->selectedItems();
+    int selectItemsCount =selectItems.count();
+    QMenu menu;
+    QMimeData * mp = const_cast<QMimeData *>(QApplication::clipboard()->mimeData()) ;
+    ShapeMimeData * data = dynamic_cast< ShapeMimeData*>( mp );
+    if ( data ){
+        QAction * pasteAction = menu.addAction("粘贴图元");
+        connect(pasteAction,SIGNAL(triggered()),this,SLOT(on_paste));
+    }
+    if(selectItemsCount >0)
+    {
+        QAction * copyAction = menu.addAction("复制图元(+30)");
+        connect(copyAction,SIGNAL(triggered()),this,SLOT(on_copy));
+        QAction * cutAction = menu.addAction("剪切图元");
+        connect(cutAction,SIGNAL(triggered()),this,SLOT(on_cut));
+        if(selectItemsCount >1)
+        {
+            QAction *assemblageAction = menu.addAction("组合图元");
+            connect(assemblageAction, SIGNAL(triggered(bool)),
+                    this,SLOT(onAssemblageAction(bool)));
+        }
+        QAction * rotation1Action = menu.addAction("旋转图元(+30)");
+        connect(rotation1Action, SIGNAL(triggered(bool)),
+                this,SLOT(onRotation1Action(bool)));
+        QAction *rotation2Action = menu.addAction("旋转图元(-30)");
+        connect(rotation2Action, SIGNAL(triggered(bool)),
+                this,SLOT(onRotation2Action(bool)));
+        QAction *deleteAction = menu.addAction("删除图元");
+        connect(deleteAction, SIGNAL(triggered(bool)),
+                this,SLOT(onDeleteAction(bool)));
+    }
+
+    menu.exec(event->globalPos());
+
+}
+
+void PaintView::on_copy()
+{
+
+    ShapeMimeData * data = new ShapeMimeData(  this->scene()->selectedItems() );
+    QApplication::clipboard()->setMimeData(data);
+}
+
+void PaintView::on_paste()
+{
+
+}
+
+void PaintView::on_cut()
+{
+
+}
+void PaintView::mouseReleaseEvent(QMouseEvent *event)
+{
+    if (event->button() == _translateButton)
+        _bMouseTranslate = false;
+
+    QGraphicsView::mouseReleaseEvent(event);
+}
+
+void PaintView::resizeEvent(QResizeEvent *event)
+{
+  this->scene()->setSceneRect(this->rect());
+}
+void PaintView::translate(QPointF delta)
+{
+    // 根据当前 zoom 缩放平移数
+    delta *= _scaleValue;
+    delta *= _translateSpeed;
+
+    // view 根据鼠标下的点作为锚点来定位 scene
+    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+    QPoint newCenter(VIEW_WIDTH / 2 - delta.x(),  VIEW_HEIGHT / 2 - delta.y());
+    centerOn(mapToScene(newCenter));
+
+    // scene 在 view 的中心点作为锚点
+    setTransformationAnchor(QGraphicsView::AnchorViewCenter);
+}
+
+
+void PaintView::keyPressEvent(QKeyEvent *event)
+{
+    QList<QGraphicsItem *>  selectItems=this->scene()->selectedItems();
+    int selectItemsCount =selectItems.count();
+    switch (event->key()) {
+
+    case Qt::Key_Up:
+        if(selectItemsCount==0)
+            translate(QPointF(0, -2));  // 上移
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                selectItems[i]->setPos(selectItems[i]->pos().rx(),selectItems[i]->pos().ry()-1);
+            }
+        }
+
+        break;
+    case Qt::Key_Down:
+        if(selectItemsCount==0)
+            translate(QPointF(0, 2));  // 下移
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                selectItems[i]->setPos(selectItems[i]->pos().rx(),selectItems[i]->pos().ry()+1);
+            }
+        }
+
+        break;
+    case Qt::Key_Left:
+        if(selectItemsCount==0)
+            translate(QPointF(-2, 0));  // 左移
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                selectItems[i]->setPos(selectItems[i]->pos().rx()-1,selectItems[i]->pos().ry());
+            }
+        }
+        break;
+    case Qt::Key_Right:
+        if(selectItemsCount==0)
+            translate(QPointF(2, 0));  // 左移
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                selectItems[i]->setPos(selectItems[i]->pos().rx()+1,selectItems[i]->pos().ry());
+            }
+        }
+        break;
+    case Qt::Key_Plus:  // 放大
+        if(selectItemsCount==0)
+            ZoomIn();
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                qreal scaleSize=selectItems[i]->scale()+0.2;
+                if(scaleSize>20) scaleSize=20;
+                QPointF centerPos=  selectItems[i]->boundingRect().center() ;
+                selectItems[i]->setTransformOriginPoint(centerPos);
+                selectItems[i]->setScale(scaleSize);
+            }
+        }
+        break;
+    case Qt::Key_Minus:  // 缩小
+        if(selectItemsCount==0)
+            ZoomOut();
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                qreal scaleSize=selectItems[i]->scale()-0.2;
+                if(scaleSize<0.05) scaleSize=0.05;
+                QPointF centerPos=  selectItems[i]->boundingRect().center() ;
+                selectItems[i]->setTransformOriginPoint(centerPos);
+                selectItems[i]->setScale(scaleSize);
+            }
+        }
+        break;
+    case Qt::Key_Space:  // 逆时针旋转
+        if(selectItemsCount==0)
+            rotate(-90);
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                //图元自转
+                QPointF centerPos=  selectItems[i]->boundingRect().center() ;
+                selectItems[i]->setTransformOriginPoint(centerPos);
+                selectItems[i]->setRotation(selectItems[i]->rotation()-1);
+            }
+        }
+        break;
+    case Qt::Key_Enter:  // 顺时针旋转
+    case Qt::Key_Return:
+        if(selectItemsCount==0)
+            rotate(90);
+        else
+        {
+            for(int i=0; i<selectItemsCount ;i++)
+            {
+                //图元自转
+                QPointF centerPos=  selectItems[i]->boundingRect().center() ;
+                selectItems[i]->setTransformOriginPoint(centerPos);
+                selectItems[i]->setRotation(selectItems[i]->rotation()+1);
+            }
+        }
+        break;
+    default:
+        QGraphicsView::keyPressEvent(event);
+    }
+}
+void PaintView::SetTranslateSpeed(qreal speed)
+{
+    // 建议速度范围
+    Q_ASSERT_X(speed >= 0.0 && speed <= 5.0,
+               "InteractiveView::setTranslateSpeed", "Speed should be in range [0.0,5.0].");
+    _translateSpeed = speed;
+}

+ 45 - 0
PaintView.h

@@ -0,0 +1,45 @@
+#pragma once
+#include "preheader.h"
+#include "ShapeMimeData.h"
+#include <QGraphicsItem>
+class PaintView : public QGraphicsView
+{
+    Q_OBJECT
+
+public:
+    explicit PaintView(QWidget *parent = 0);
+    ~PaintView();
+
+    void ZoomOut();
+    void ZoomIn();
+    void SetTranslateSpeed(qreal speed);
+private:
+    Qt::MouseButton _translateButton;  // 平移按钮
+    qreal  _zoomDelta;  // 缩放的增量
+    qreal _scaleValue;  // 缩放值
+    QPoint  _lastMousePos;  // 鼠标最后按下的位置
+    qreal _translateSpeed;  // 平移速度
+    bool _bMouseTranslate;
+
+    void zoom(float scaleFactor);
+    void paintEvent(QPaintEvent *event);
+    void wheelEvent(QWheelEvent *event);
+    void keyPressEvent(QKeyEvent *event);
+    void translate(QPointF delta);
+    void mouseMoveEvent(QMouseEvent *event);
+    void mousePressEvent(QMouseEvent *event);
+    void mouseReleaseEvent(QMouseEvent *event);
+    void resizeEvent(QResizeEvent *event);
+    void contextMenuEvent(QContextMenuEvent *event);
+
+private slots:
+    void onAssemblageAction(bool);
+    void onRotation1Action(bool);
+    void onRotation2Action(bool);
+    void onDeleteAction(bool) ;
+    void on_copy();
+    void on_paste();
+    void on_cut();
+
+
+};

+ 21 - 0
PaintWidget.ui

@@ -0,0 +1,21 @@
+<ui version="4.0">
+ <author/>
+ <comment/>
+ <exportmacro/>
+ <class>PaintWidget</class>
+ <widget name="PaintWidget" class="QWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+ </widget>
+ <pixmapfunction/>
+ <connections/>
+</ui>

+ 16 - 0
ShapeMimeData.cpp

@@ -0,0 +1,16 @@
+#include "ShapeMimeData.h"
+
+ShapeMimeData::ShapeMimeData(QList<QGraphicsItem *> items)
+{
+    foreach (QGraphicsItem *item , items ) {
+//       AbstractShape *sp = qgraphicsitem_cast<AbstractShape*>(item);
+//       m_items.append(sp->copy());
+    }
+}
+ShapeMimeData::~ShapeMimeData()
+{
+    foreach (QGraphicsItem *item , m_items ) {
+        delete item;
+    }
+    m_items.clear();
+}

+ 13 - 0
ShapeMimeData.h

@@ -0,0 +1,13 @@
+#pragma once
+#include "preheader.h"
+
+class ShapeMimeData :public QMimeData
+{
+    Q_OBJECT
+public:
+    ShapeMimeData( QList<QGraphicsItem * > items);
+    ~ShapeMimeData();
+    QList<QGraphicsItem *> items() const ;
+private:
+    QList<QGraphicsItem * > m_items;
+};

+ 35 - 0
WordEdit.cpp

@@ -0,0 +1,35 @@
+#include "WordEditt.h"
+#include "ui_WordEdit.h"
+#include "qtoolbar.h"
+#include "QVBoxLayout"
+
+WordEdit::WordEdit(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::WordEdit)
+{
+    ui->setupUi(this);
+    QToolBar* locToolBar = new QToolBar(tr("文档"),this); //创建工具栏
+    locToolBar->addAction(ui->fileOpen);
+        locToolBar->addAction(ui->saveAction);
+        locToolBar->addAction(ui->saveAsAction);
+        locToolBar->addSeparator();
+//        locToolBar->addAction(ui->actCut);
+//        locToolBar->addAction(ui->actCopy);
+//        locToolBar->addAction(ui->actPaste);
+//        locToolBar->addAction(ui->actUndo);
+//        locToolBar->addAction(ui->actRedo);
+//        locToolBar->addSeparator();
+        locToolBar->addAction(ui->closeAction);
+    locToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    QVBoxLayout *Layout = new QVBoxLayout();
+    Layout->addWidget(locToolBar); //设置工具栏和编辑器上下布局
+    Layout->addWidget(ui->plainTextEdit);
+    Layout->setContentsMargins(2,2,2,2); //减小边框的宽度
+    Layout->setSpacing(2);
+    this->setLayout(Layout); //设置布局
+}
+
+WordEdit::~WordEdit()
+{
+    delete ui;
+}

+ 79 - 0
WordEdit.ui

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WordEdit</class>
+ <widget class="QWidget" name="WordEdit">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1070</width>
+    <height>660</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>文本编辑器</string>
+  </property>
+  <widget class="QPlainTextEdit" name="plainTextEdit">
+   <property name="geometry">
+    <rect>
+     <x>170</x>
+     <y>80</y>
+     <width>571</width>
+     <height>431</height>
+    </rect>
+   </property>
+  </widget>
+  <action name="fileOpen">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/open.png</normaloff>:/new/prefix1/images/open.png</iconset>
+   </property>
+   <property name="text">
+    <string>打开</string>
+   </property>
+   <property name="toolTip">
+    <string>打开文档</string>
+   </property>
+  </action>
+  <action name="closeAction">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/close.png</normaloff>:/new/prefix1/images/close.png</iconset>
+   </property>
+   <property name="text">
+    <string>关闭</string>
+   </property>
+   <property name="toolTip">
+    <string>关闭窗口</string>
+   </property>
+  </action>
+  <action name="saveAction">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/save.ico</normaloff>:/new/prefix1/images/save.ico</iconset>
+   </property>
+   <property name="text">
+    <string>保存</string>
+   </property>
+   <property name="toolTip">
+    <string>保存文件</string>
+   </property>
+  </action>
+  <action name="saveAsAction">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/saveas.png</normaloff>:/new/prefix1/images/saveas.png</iconset>
+   </property>
+   <property name="text">
+    <string>另存为</string>
+   </property>
+   <property name="toolTip">
+    <string>另存为</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="qrc.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 22 - 0
WordEditt.h

@@ -0,0 +1,22 @@
+#ifndef WORDEDITT_H
+#define WORDEDITT_H
+
+#include <QWidget>
+
+namespace Ui {
+class WordEdit;
+}
+
+class WordEdit : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit WordEdit(QWidget *parent = nullptr);
+    ~WordEdit();
+
+private:
+    Ui::WordEdit *ui;
+};
+
+#endif // WORDEDITT_H

+ 626 - 0
drawtool.cpp

@@ -0,0 +1,626 @@
+#include "drawtool.h"
+#include "GraphicsEllipseItem.h"
+#include "GraphicsTextItem.h"
+#include "GraphicsLineItem.h"
+#include "GraphicsTriangleItem.h"
+#define PI 3.14
+
+QList<DrawTool*> DrawTool::c_tools;
+QPointF DrawTool::c_down;
+QPointF DrawTool::c_last;
+quint32 DrawTool::c_nDownFlags;
+
+DrawBaseShape DrawTool::c_drawShape = selection;
+
+static SelectTool selectTool;
+static PenPathTool penPathTool(penPath);
+static LineTool   lineTool(line);
+static ImageTool   imageTool(image);
+static RectTool   rectTool(rectangle);
+static RectTool   triangleTool(triangle);
+static RectTool   roundRectTool(roundrect);
+static RectTool   ellipseTool(ellipse);
+static RotationTool rotationTool;
+static ArrowItem arrowTool(arrowLine);
+
+
+enum SelectMode
+{
+    none,
+    netSelect,
+    move, //移动
+    size, //改变大小
+    rotate //反转
+};
+SelectMode selectMode = none;
+
+SizeHandleRect::Direction nDragHandle = SizeHandleRect::None;
+
+static void setCursor(QGraphicsScene * scene , const QCursor & cursor )
+{
+    QList<QGraphicsView*> views  = scene->views();
+    if ( views.count() > 0 ){
+        QGraphicsView * view = views.first();
+        view->setCursor(cursor);
+    }
+}
+
+DrawTool::DrawTool(DrawBaseShape shape)
+{
+    m_drawShape = shape ;
+    c_tools.push_back(this);
+}
+
+void DrawTool::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    c_down = event->scenePos();
+    c_last = event->scenePos();
+}
+
+void DrawTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    c_last = event->scenePos();
+}
+
+void DrawTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    if (event->scenePos() == c_down)
+        c_drawShape = selection;
+    setCursor(scene,Qt::ArrowCursor);
+
+}
+
+DrawTool *DrawTool::findTool(DrawBaseShape drawShape)
+{
+    QList<DrawTool*>::const_iterator iter = c_tools.constBegin();
+    for ( ; iter != c_tools.constEnd() ; ++iter ){
+        if ((*iter)->m_drawShape == drawShape )
+            return (*iter);
+    }
+    return 0;
+}
+
+SelectTool::SelectTool()
+    :DrawTool(selection)
+{
+    m_lastSize.setHeight(0);
+    m_lastSize.setWidth(0);
+    dashRect = 0;
+    dashLine = 0;
+    m_hoverSizer = false;
+
+}
+
+void SelectTool::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mousePressEvent(event,scene);
+
+    if (!m_hoverSizer)
+        scene->mouseEvent(event);
+
+    selectMode = none;
+    QList<QGraphicsItem *> items = scene->selectedItems();
+    GraphicsItem *item = 0;
+    if ( items.count() == 1 )
+    {
+        item = qgraphicsitem_cast<GraphicsItem*>(items.first());
+
+    }
+    if ( item != 0 &&
+         item->type() !=GraphicsItem::UserType+3){
+
+        nDragHandle = item->hitTest(event->scenePos());
+        if ( nDragHandle !=SizeHandleRect::None)
+            selectMode = size;
+        else
+            selectMode =  move;
+    }
+
+
+    if( selectMode == none ){
+        selectMode = netSelect;
+        QList<QGraphicsView*> views  = scene->views();
+        if ( views.count() > 0 ){
+            QGraphicsView * view = views.first();
+            view->setDragMode(QGraphicsView::RubberBandDrag);
+        }
+    }
+
+    if ( selectMode == move && items.count() == 1 ){
+
+        if (dashRect ){
+            scene->removeItem(dashRect);
+            delete dashRect;
+            dashRect = 0;
+        }
+        if (dashLine ) {
+            scene->removeItem(dashLine);
+            delete dashLine;
+            dashLine = 0;
+        }
+
+        item->setPos(item->mapToScene(item->boundingRect().topLeft()));
+        item->resetShape();
+        dashRect = new QGraphicsPathItem(item->shape());
+        dashRect->setPen(Qt::DashLine);
+        dashRect->setPos(item->pos());
+        //dashRect->setTransformOriginPoint(item->transformOriginPoint());
+        dashRect->setTransform(item->transform());
+        dashRect->setRotation(item->rotation());
+        scene->addItem(dashRect);
+
+        dashLine = new QGraphicsLineItem();
+        dashLine->setPos(item->pos());
+        dashLine->setPen(Qt::DashLine);
+        scene->addItem(dashLine);
+
+    }
+}
+
+void SelectTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mouseMoveEvent(event,scene);
+    bool isGroup = false;
+    QList<QGraphicsItem *> items = scene->selectedItems();
+    GraphicsItem * item = 0;
+    if ( items.count() == 1 )
+    {
+        item = qgraphicsitem_cast<GraphicsItem*>(items.first());
+        if ( item != 0 ){
+            if(item->type() ==GraphicsItem::UserType+3)
+            {
+                scene->mouseEvent(event);
+                scene->update();
+                return;
+            }
+            if ( nDragHandle != SizeHandleRect::None && selectMode == size ){
+                item->resizeTo(nDragHandle,c_last);
+            }
+            else if(nDragHandle == SizeHandleRect::None && selectMode == selection ){
+
+                SizeHandleRect::Direction handle = item->hitTest(event->scenePos());
+                if ( handle != SizeHandleRect::None){
+                    setCursor(scene,item->getCursor(handle));
+                    m_hoverSizer = true;
+                }else{
+                    setCursor(scene,Qt::ArrowCursor);
+                    m_hoverSizer = false;
+                }
+            }
+        }
+
+        QGraphicsItemGroup *item1 = qgraphicsitem_cast<QGraphicsItemGroup*>(items.first());
+        if ( item1 != NULL ){
+            isGroup = true;
+        }
+    }
+    if ( selectMode == move ){
+        if ( dashRect )
+        {
+            dashRect->setPos(c_last);
+            dashLine->setLine(QLineF(dashLine->mapFromItem(item,item->boundingRect().topLeft()),
+                                     dashLine->mapFromScene(c_last)));
+        }
+    }
+    else if ((selectMode != size  && items.count() > 0) || isGroup )
+    {
+        scene->mouseEvent(event);
+    }
+    scene->update();
+}
+
+void SelectTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mouseReleaseEvent(event,scene);
+
+    QList<QGraphicsItem *> items = scene->selectedItems();
+    if ( items.count() == 1 ){
+        GraphicsItem * item = qgraphicsitem_cast<GraphicsItem*>(items.first());
+        if ( item != 0 )
+        {
+            if(selectMode == move && c_last != c_down ){
+                item->setPos(c_last);
+            }
+            item->resetArrow();
+        }
+    }
+    if (selectMode == netSelect ){
+        QList<QGraphicsView*> views  = scene->views();
+        if ( views.count() > 0 ){
+            QGraphicsView * view = views.first();
+            view->setDragMode(QGraphicsView::NoDrag);
+        }
+    }
+
+    if (dashRect ){
+        scene->removeItem(dashRect);
+        delete dashRect;
+        dashRect = 0;
+
+        scene->removeItem(dashLine);
+        delete dashLine;
+        dashLine = 0;
+    }
+
+    selectMode = none;
+    nDragHandle = SizeHandleRect::None;
+    m_hoverSizer = false;
+    scene->mouseEvent(event);
+}
+
+
+RotationTool::RotationTool()
+    :DrawTool(rotation)
+{
+    lastAngle == 0;
+    dashRect = 0;
+}
+
+void RotationTool::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mousePressEvent(event,scene);
+    QList<QGraphicsItem *> items = scene->selectedItems();
+    if ( items.count() == 1 ){
+        GraphicsItem * item = qgraphicsitem_cast<GraphicsItem*>(items.first());
+        if ( item != 0 ){
+            nDragHandle = item->hitTest(event->scenePos());
+            if ( nDragHandle !=SizeHandleRect::None)
+            {
+                QPointF origin = item->mapToScene(item->boundingRect().center());
+
+                qreal len_y = c_last.y() - origin.y();
+                qreal len_x = c_last.x() - origin.x();
+
+                qreal angle = atan2(len_y,len_x)*180/PI;
+
+                lastAngle = angle;
+                selectMode = rotate;
+
+                if (dashRect ){
+                    scene->removeItem(dashRect);
+                    delete dashRect;
+                    dashRect = 0;
+                }
+
+                dashRect = new QGraphicsPathItem(item->shape());
+                dashRect->setPen(Qt::DashLine);
+                dashRect->setPos(item->pos());
+                dashRect->setTransformOriginPoint(item->transformOriginPoint());
+                dashRect->setTransform(item->transform());
+                dashRect->setRotation(item->rotation());
+                scene->addItem(dashRect);
+
+                setCursor(scene,QCursor(QPixmap(":/new/prefix1/images/rotation.ico")));
+            }
+            else{
+
+                scene->clearSelection();
+                c_drawShape = selection;
+            }
+        }
+    }
+}
+
+void RotationTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mouseMoveEvent(event,scene);
+
+    QList<QGraphicsItem *> items = scene->selectedItems();
+    if ( items.count() == 1 ){
+        GraphicsItem * item = qgraphicsitem_cast<GraphicsItem*>(items.first());
+        if ( item != 0  && nDragHandle !=SizeHandleRect::None && selectMode == rotate ){
+
+
+            QPointF origin = item->mapToScene(item->boundingRect().center());
+
+            qreal len_y = c_last.y() - origin.y();
+            qreal len_x = c_last.x() - origin.x();
+
+            qreal angle = atan2(len_y,len_x)*180/PI;
+
+            angle = item->rotation() + int(angle - lastAngle) ;
+
+            if ( angle > 360 )
+                angle -= 360;
+
+            if ( dashRect ){
+                dashRect->setRotation( angle );
+                scene->update();
+            }
+
+            setCursor(scene,QCursor(QPixmap(":/new/prefix1/images/rotation.ico")));
+        }
+        else if ( item )
+        {
+            SizeHandleRect::Direction handle = item->hitTest(event->scenePos());
+            if ( handle != SizeHandleRect::None)
+                setCursor(scene,QCursor(QPixmap(":/new/prefix1/images/rotation.ico")));
+            else
+                setCursor(scene,Qt::ArrowCursor);
+        }
+    }
+}
+
+void RotationTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mouseReleaseEvent(event,scene);
+
+    QList<QGraphicsItem *> items = scene->selectedItems();
+    if ( items.count() == 1 ){
+        GraphicsItem * item = qgraphicsitem_cast<GraphicsItem*>(items.first());
+        if ( item != 0  && nDragHandle !=SizeHandleRect::None && selectMode == rotate ){
+
+            QPointF origin = item->mapToScene(item->boundingRect().center());
+
+            QPointF delta = c_last - origin ;
+            qreal len_y = c_last.y() - origin.y();
+            qreal len_x = c_last.x() - origin.x();
+            qreal angle = atan2(len_y,len_x)*180/PI;
+            angle = item->rotation() + int(angle - lastAngle) ;
+            if ( angle > 360 )
+                angle -= 360;
+            item->setRotation( angle );
+        }
+    }
+
+    setCursor(scene,Qt::ArrowCursor);
+    selectMode = none;
+    nDragHandle = SizeHandleRect::None;
+    lastAngle = 0;
+    if (dashRect ){
+        scene->removeItem(dashRect);
+        delete dashRect;
+        dashRect = 0;
+    }
+    qDebug() << " RotationTool release:" <<event->scenePos();
+}
+
+/*************************************ImageTool*******************/
+ImageTool::ImageTool(DrawBaseShape drawShape)
+    :DrawTool(drawShape)
+{
+
+}
+void ImageTool::setPicture(QString path )
+{
+    _imgPath =path;
+
+}
+void ImageTool::mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene )
+{
+    DrawTool::mousePressEvent(event,scene);
+    scene->clearSelection();
+    QPixmap pixmap;
+    bool ok= pixmap.load(_imgPath);
+    if(! ok)
+        return;
+    switch ( c_drawShape ){
+    case image:
+        item = new GraphicsPixmapItem(pixmap,NULL);
+        break;
+
+    }
+    if ( item == 0) return;
+    item->setPos(event->scenePos());
+    scene->addItem(item);
+    item->setSelected(true);
+    selectMode = size;
+    nDragHandle = SizeHandleRect::RightBottom;
+}
+void ImageTool::mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene )
+{
+    setCursor(scene,Qt::CrossCursor);
+    selectTool.mouseMoveEvent(event,scene);
+}
+void ImageTool::mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene )
+{
+    if ( event->scenePos() == c_down ){
+        if ( item != 0)
+            scene->removeItem(item);
+        selectTool.mousePressEvent(event,scene);
+    }
+    selectTool.mouseReleaseEvent(event,scene);
+}
+
+
+
+/*************************************RectTool*******************/
+RectTool::RectTool(DrawBaseShape drawShape)
+    :DrawTool(drawShape)
+{
+}
+
+void RectTool::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mousePressEvent(event,scene);
+    scene->clearSelection();
+
+    bool isSquare =false;
+    if (event->button() == Qt::LeftButton)
+    {
+        if (QApplication::keyboardModifiers()== Qt::ControlModifier)
+        {
+            isSquare =true;
+        }
+    }
+    switch ( c_drawShape ){
+    case rectangle:
+        item = new GraphicsRectItem(QRect(0,0,0,0),NULL);
+        item->setPen(Qt::NoPen);
+        break;
+    case ellipse:
+        item = new GraphicsEllipseItem(QRect(0,0,0,0),NULL);
+        item->setPen(Qt::NoPen);
+        break;
+    case triangle:
+        item = new GraphicsTriangleItem(QRect(0,0,0,0),NULL);
+        item->setPen(Qt::NoPen);
+        break;
+    }
+    if ( item == 0) return;
+    if(isSquare)
+        item->setIsSquare();
+    item->setBorderColor(_mColor);
+    item->setPos(event->scenePos());
+    scene->addItem(item);
+    item->setSelected(true);
+    selectMode = size;
+    nDragHandle = SizeHandleRect::RightBottom;
+}
+
+void RectTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    setCursor(scene,Qt::CrossCursor);
+    selectTool.mouseMoveEvent(event,scene);
+}
+
+void RectTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    if ( event->scenePos() == c_down ){
+        if (item != 0)
+            scene->removeItem(item);
+        selectTool.mousePressEvent(event,scene);
+    }
+    selectTool.mouseReleaseEvent(event,scene);
+}
+
+/////////****************PenPath************/////////////////////
+PenPathTool::PenPathTool(DrawBaseShape drawShape)
+    :DrawTool(drawShape)
+{
+
+    _path =nullptr;
+}
+void PenPathTool::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mousePressEvent(event,scene);
+    scene->clearSelection();
+
+    switch ( c_drawShape ){
+    case penPath:
+        SafeDelete(_path);
+        _path = new QPainterPath;
+        _path->moveTo(event->scenePos());
+        item = new QGraphicsPathItem(*_path,nullptr);
+        item->setFlag(QGraphicsItem::ItemIsMovable, true);
+        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
+        break;
+    }
+    if ( item == 0) return;
+
+    isDrawing =true;
+    scene->addItem(item);
+    QPen pen_bak=item->pen();
+    pen_bak.setWidth(9);
+    pen_bak.setColor(_mColor);
+    item->setPen(pen_bak);
+
+}
+
+void PenPathTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    if(isDrawing)
+    {
+        QPixmap pixmap(":/new/prefix1/images/ic_sidebar_pencil.png");
+        //定义大小
+        QSize picSize(8, 8);
+        //缩放图片,按比例
+        QPixmap scaledPixmap = pixmap.scaled(picSize, Qt::KeepAspectRatio);
+        //设置样式
+        QCursor cursor(scaledPixmap, -1, -1);
+        setCursor(scene,cursor);
+        _path->lineTo(event->scenePos());
+        item->setPath(*_path);
+    }
+}
+
+void PenPathTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    isDrawing=false;
+}
+
+/////////****************LineTool************/////////////////////
+LineTool::LineTool(DrawBaseShape drawShape)
+    :DrawTool(drawShape)
+{
+
+    item =nullptr;
+}
+void LineTool::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mousePressEvent(event,scene);
+    scene->clearSelection();
+
+    switch ( c_drawShape ){
+    case line:
+        item = new GraphicsLineItem(QLineF(event->scenePos(),
+                                           event->scenePos()));
+        item->setFlag(QGraphicsItem::ItemIsMovable, true);
+        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
+        break;
+    }
+    if ( item == 0) return;
+
+    isDrawing =true;
+    // 设置画笔
+    QPen pen = item->pen();
+    pen.setColor(_mColor);
+    pen.setWidth(4);
+    item->setPen(pen);
+    scene->addItem(item);
+}
+
+void LineTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    if(isDrawing)
+    {
+        QLineF newLine(item->line().p1(), event->scenePos());
+        item->setLine(newLine);
+    }
+}
+
+void LineTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    isDrawing=false;
+}
+/////////****************ArrowItem************/////////////////////
+
+ArrowItem::ArrowItem(DrawBaseShape drawShape)
+    :DrawTool(drawShape)
+{
+}
+
+void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    DrawTool::mousePressEvent(event,scene);
+    scene->clearSelection();
+    switch ( c_drawShape ){
+    case arrowLine:
+        item = new GraphicsArrowItem();
+        item->setFlag(QGraphicsItem::ItemIsMovable, true);
+        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
+
+        item->endPos= event->scenePos();
+        item->startPos= event->scenePos();
+        break;
+    }
+    if ( item == 0) return;
+    isDrawing =true;
+    item->setBorderColor(_mColor);
+    scene->addItem(item);
+}
+
+void ArrowItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+    if(isDrawing)
+    {
+         item->endPos= event->scenePos();
+         scene->update();
+    }
+}
+
+void ArrowItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, MainPaintScene *scene)
+{
+   isDrawing=false;
+}
+

+ 147 - 0
drawtool.h

@@ -0,0 +1,147 @@
+#pragma once
+#include "preheader.h"
+#include "MainPaintScenee.h"
+#include "GraphicsRectItem.h"
+#include "GraphicsTextItem.h"
+#include "GraphicsPixmapItem.h"
+#include "GraphicsPathItem.h"
+#include "GraphicsArrowItem.h"
+#include "GraphicsLineItem.h"
+QT_BEGIN_NAMESPACE
+class QGraphicsScene;
+class QGraphicsSceneMouseEvent;
+class QMenu;
+class QPointF;
+class QGraphicsLineItem;
+class QFont;
+class QGraphicsTextItem;
+class QColor;
+class QAbstractGraphicsShapeItem;
+class PaintView;
+QT_END_NAMESPACE
+
+class MainPaintScene;
+class GraphicsItem;
+
+class DrawTool
+{
+public:
+    DrawTool( DrawBaseShape shape =DrawBaseShape::selection );
+
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event, MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+
+    virtual void setPicture(QString path=""){}
+
+    void setCurrentColor(QColor color)
+    {
+        _mColor =color;
+    }
+    QColor _mColor;
+    DrawBaseShape m_drawShape;
+    static DrawTool * findTool( DrawBaseShape drawShape );
+    static QList<DrawTool*> c_tools;
+    static QPointF c_down;
+    static quint32 c_nDownFlags;
+    static QPointF c_last;
+    static DrawBaseShape c_drawShape;
+};
+
+class SelectTool : public DrawTool
+{
+public:
+    SelectTool();
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    QSizeF  m_lastSize;
+    QGraphicsPathItem * dashRect;
+    QGraphicsLineItem * dashLine;
+    bool m_hoverSizer;
+
+};
+
+class  RotationTool : public DrawTool
+{
+public:
+    RotationTool();
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    qreal lastAngle;
+    QGraphicsPathItem * dashRect;
+};
+
+
+class ImageTool : public DrawTool
+{
+public:
+    ImageTool(DrawBaseShape drawShape);
+    virtual void setPicture(QString path="");
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    GraphicsPixmapItem * item;
+    QString _imgPath;
+};
+
+class RectTool : public DrawTool
+{
+public:
+    RectTool(DrawBaseShape drawShape);
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    GraphicsRectItem * item;
+};
+
+// 笔
+class PenPathTool : public DrawTool
+{
+public:
+    PenPathTool(DrawBaseShape drawShape);
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    QGraphicsPathItem * item;
+    QPainterPath *_path;
+    bool isDrawing; //绘制中
+};
+
+//线段
+class LineTool : public DrawTool
+{
+public:
+    LineTool(DrawBaseShape drawShape);
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    GraphicsLineItem * item;
+    bool isDrawing; //绘制中
+};
+
+//箭头
+class ArrowItem : public DrawTool
+{
+public:
+    ArrowItem(DrawBaseShape drawShape);
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    GraphicsArrowItem * item;
+    bool isDrawing;
+};
+
+// 文本
+class TextTool : public DrawTool
+{
+
+public:
+    TextTool(DrawBaseShape drawShape);
+    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene ) ;
+    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , MainPaintScene * scene );
+    GraphicsTextItem *textItem;
+};
+

+ 86 - 0
handprint_identification_reports.pro

@@ -0,0 +1,86 @@
+QT       += core gui sql axcontainer
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# You can make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+    GraphicsArrowItem.cpp \
+    GraphicsEllipseItem.cpp \
+    GraphicsItem.cpp \
+    GraphicsItemGroup.cpp \
+    GraphicsLineItem.cpp \
+    GraphicsPathItem.cpp \
+    GraphicsPixmapItem.cpp \
+    GraphicsRectItem.cpp \
+    GraphicsTextItem.cpp \
+    GraphicsTriangleItem.cpp \
+    ImageEdit.cpp \
+    MainPaintScene.cpp \
+    PaintView.cpp \
+    ShapeMimeData.cpp \
+    WordEdit.cpp \
+    drawtool.cpp \
+    hmerge.cpp \
+    imagecropperlabel.cpp \
+    imagecropperdemo.cpp \
+    main.cpp \
+    mainwindow.cpp \
+    mylabel.cpp \
+    reporting.cpp \
+    sizehandle.cpp \
+    vmerge.cpp
+
+HEADERS += \
+    GraphicsArrowItem.h \
+    GraphicsEllipseItem.h \
+    GraphicsItem.h \
+    GraphicsItemGroup.h \
+    GraphicsLineItem.h \
+    GraphicsPathItem.h \
+    GraphicsPixmapItem.h \
+    GraphicsRectItem.h \
+    GraphicsTextItem.h \
+    GraphicsTriangleItem.h \
+    ImageEdit.h \
+    MainPaintScenee.h \
+    PaintView.h \
+    ShapeMimeData.h \
+    WordEditt.h \
+    drawtool.h \
+    hmerge.h \
+    imagecropperdialog.h \
+    imagecropperlabel.h \
+    imagecropperdemo.h \
+    mainwindow.h \
+    mylabel.h \
+    preheader.h \
+    reporting.h \
+    sizehandle.h \
+    vmerge.h
+
+FORMS += \
+    ImageEdit.ui \
+    PaintWidget.ui \
+    WordEdit.ui \
+    hmerge.ui \
+    mainwindow.ui \
+    reporting.ui \
+    vmerge.ui
+
+TRANSLATIONS += \
+    handprint_identification_reports_zh_CN.ts
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
+
+RESOURCES += \
+    qrc.qrc
+
+RC_ICONS = logo.ico

+ 3 - 0
handprint_identification_reports_zh_CN.ts

@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="handprint_identification_reports_zh_CN"></TS>

+ 150 - 0
hmerge.cpp

@@ -0,0 +1,150 @@
+#include "hmerge.h"
+#include "ui_hmerge.h"
+#include "qtoolbar.h"
+#include "QVBoxLayout"
+#include "QDir"
+#include "QFileDialog"
+#include "QDebug"
+#include <QWheelEvent>
+#include <QMenu>
+#include <QPainter>
+#include <QScrollArea>
+#include<QVector>
+
+#include<QDesktopWidget>
+
+#include<QScreen>
+
+HMerge::HMerge(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::HMerge)
+{
+
+    ui->setupUi(this);
+    //使用UI设计的Actions设计工具栏
+    QToolBar* locToolBar = new QToolBar(tr("图片"),this); //创建工具栏
+    locToolBar->addAction(ui->imageOpen);
+    connect (ui->imageOpen,SIGNAL(triggered(bool)),this,SLOT(imageOpen()));
+    locToolBar->addAction(ui->saveAction);
+    connect (ui->saveAction,SIGNAL(triggered(bool)),this,SLOT(imageSave()));
+    locToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+    QVBoxLayout *Layout = new QVBoxLayout();//图片标注主界面垂直布局
+    Layout->addWidget(locToolBar); //设置工具栏和编辑器上下布局
+    QHBoxLayout *layout1=new QHBoxLayout();//工具栏下方水平布局,放入两个垂直布局
+    QVBoxLayout *leftLayout=new QVBoxLayout();//工具栏下方左侧垂直布局
+    label1=new QLabel(tr("1.5x1.9"));
+    leftLayout->addStretch(1);
+    leftLayout->addWidget(label1);
+    leftLayout->addStretch(1);
+    label2=new QLabel(tr("5.5x7"));
+    QVBoxLayout *rightLayout=new QVBoxLayout();//工具栏下方右侧垂直布局
+    //        label2->setStyleSheet("border:2px solid red;");
+    //    label2->setPixmap(fitpixmap);
+    rightLayout->addWidget(label2);
+    layout1->addLayout(leftLayout);
+    //    layout1->addStretch();
+    layout1->addLayout(rightLayout);
+    //    Layout->setContentsMargins(2,2,2,2); //减小边框的宽度
+    //    Layout->setSpacing(2);
+    Layout->addLayout(layout1);
+    this->setLayout(Layout); //设置布局
+}
+
+void HMerge::imageOpen(){
+    //    //选择单个文件
+    QString curPath=QDir::currentPath();//获取系统当前目录
+    //获取应用程序的路径
+    QString dlgTitle="选择一个文件"; //对话框标题
+    QString filter="图片文件(*.jpg *.jpeg *.gif *.png)"; //文件过滤器
+    LocalFileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
+    QImage Image;
+    Image.load(LocalFileName);
+    qDebug()<<Image.width()<<Image.height();
+    double dpiX = QApplication::desktop()->physicalDpiX();
+    double dpiY = QApplication::desktop()->physicalDpiY();
+    int physicalX=(int)(dpiX*1.5/2.54+0.5f);
+    int physicalY=(int)(dpiY*1.9/2.54+0.5f);
+    qDebug()<<"aaa:"<<physicalX<<"bbb:"<<physicalY;
+    QPixmap pixmap = QPixmap::fromImage(Image);
+    QPixmap fitpixmap = pixmap.scaled(physicalX, physicalY, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 饱满填充
+    //    label1->setScaledContents(true);
+    label1->setAlignment(Qt::AlignCenter);
+    label1->setPixmap(fitpixmap);
+    int physicalX1=(int)(dpiX*5.5/2.54+0.5f);
+    int physicalY1=(int)(dpiY*7/2.54+0.5f);
+    qDebug()<<"aaa:"<<physicalX1<<"bbb:"<<physicalY1;
+    fitpixmap = pixmap.scaled(physicalX1, physicalY1, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 饱满填充
+    label2->setPixmap(fitpixmap);
+    //    label2->setScaledContents(true);
+
+    //    LocalFileName = QFileDialog::getOpenFileName(this, "Open Image", "./", tr("Images (*.png *.xpm *.jpg)"));
+
+    QFile file(LocalFileName);
+    if (!file.exists())
+        return;
+    //    ZoomValue = 1.0;
+    //    XPtInterval = 0;
+    //    YPtInterval = 0;
+    update();
+
+}
+
+//合成图片
+void HMerge::imageSave(){
+    //    QImage resultImg = QImage(orginImg.width(), orginImg.height(), QImage::Format_RGB32);
+    //    QPainter *painter = new QPainter(&resultImg);
+    //    painter->drawImage(0, 0, leftImg);
+    //    painter->drawImage(leftImg.width(), 0, rightImg);
+    //    resultImg.save("flip.jpg");
+    QString filename1 = QFileDialog::getSaveFileName(this,tr("保存图片"),"",tr("Images (*.jpg)")); //选择路径
+    QVector<QImage> vector1;
+    QImage q1,q2;
+    q1.load(LocalFileName);
+    vector1.append(q1);
+    q2.load(LocalFileName);
+    QPixmap pixmap = QPixmap::fromImage(q2);
+    QPixmap fitpixmap = pixmap.scaled(1083, 1378, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 饱满填充
+    vector1.append(fitpixmap.toImage());
+    QImage q= MergeImageH(vector1,filename1);
+}
+
+HMerge::~HMerge()
+{
+    delete ui;
+}
+QImage HMerge::MergeImageH(QVector <QImage > image, QString filename)
+{
+    int image_width=0;
+    int max_height = 0;
+    QVector <QImage > ::iterator it;
+    for(it = image.begin();it!=image.end();++it)
+    {
+        int width = (*it).width();
+        image_width += width;
+        qDebug()<<width<<(*it).height();
+        if((*it).height()>max_height)
+        {
+            max_height =(*it).height();
+        }
+    }
+    QImage result_image_h(image_width+300,max_height,QImage::Format_RGB32);
+    result_image_h.fill(Qt::white);
+    QPainter painter_h;
+    painter_h.begin(&result_image_h);
+    int x_number=0;
+    for(it = image.begin();it!=image.end();++it)
+    {
+        if(x_number==0){//左侧图片绘制上下空白区域以及中间空白区域
+            painter_h.drawImage(x_number,(*it).height(),(*it));
+            x_number += (*it).width()+300;
+        }else{
+            painter_h.drawImage(x_number,0,(*it));
+            //            x_number += (*it).width();
+        }
+    }
+    painter_h.end();
+    //    QString name = image_output_path_.append("/").append(merge_output_filename_).append(".").append(convert_format_);
+    result_image_h.save(filename,"jpg");
+    return result_image_h;
+}
+

+ 34 - 0
hmerge.h

@@ -0,0 +1,34 @@
+#ifndef HMERGE_H
+#define HMERGE_H
+
+#include <QWidget>
+#include <QLabel>
+
+namespace Ui {
+class HMerge;
+}
+
+class HMerge : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit HMerge(QWidget *parent = nullptr);
+    ~HMerge();
+
+protected:
+     QImage MergeImageH(QVector<QImage>image, QString filename);
+
+protected slots:
+    void imageOpen(); //打开文件
+    void imageSave(); //保存文件
+
+private:
+    Ui::HMerge *ui;
+    QLabel *label1;
+    QLabel *label2;
+
+    QString LocalFileName;  //图片名
+};
+
+#endif // HMERGE_H

+ 45 - 0
hmerge.ui

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>HMerge</class>
+ <widget class="QWidget" name="HMerge">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>700</width>
+    <height>631</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <action name="imageOpen">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/open.ico</normaloff>:/new/prefix1/images/open.ico</iconset>
+   </property>
+   <property name="text">
+    <string>打开</string>
+   </property>
+   <property name="toolTip">
+    <string>打开图片</string>
+   </property>
+  </action>
+  <action name="saveAction">
+   <property name="icon">
+    <iconset resource="qrc.qrc">
+     <normaloff>:/new/prefix1/images/save.png</normaloff>:/new/prefix1/images/save.png</iconset>
+   </property>
+   <property name="text">
+    <string>保存</string>
+   </property>
+   <property name="toolTip">
+    <string>保存</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="qrc.qrc"/>
+ </resources>
+ <connections/>
+</ui>

+ 484 - 0
imagecropperdemo.cpp

@@ -0,0 +1,484 @@
+#include "imagecropperdemo.h"
+#include <QFormLayout>
+#include <QColorDialog>
+#include <QVBoxLayout>
+#include <QFileDialog>
+#include <QMessageBox>
+
+#include <QDebug>
+
+ImageCropperDemo::ImageCropperDemo(QWidget* parent) :
+    QDialog(parent)
+{
+    setupLayout();
+    init();
+
+    this->setAttribute(Qt::WA_DeleteOnClose, true);
+    this->setWindowTitle("图片裁剪工具");
+}
+
+
+void ImageCropperDemo::setupLayout() {
+    imgCropperLabel = new ImageCropperLabel(600, 500, this);
+    imgCropperLabel->setFrameStyle(1);
+
+    comboOutputShape = new QComboBox(this);
+    comboCropperShape = new QComboBox(this);
+
+    labelPreviewImage = new QLabel(this);
+
+    editOriginalImagePath = new QLineEdit(this);
+    btnChooseOriginalImagePath = new QPushButton(this);
+    QHBoxLayout* hOriginalImagePathLayout = new QHBoxLayout();
+    hOriginalImagePathLayout->addWidget(editOriginalImagePath);
+    hOriginalImagePathLayout->addWidget(btnChooseOriginalImagePath);
+
+
+    //图片分辨率设置
+    editResolution = new QLineEdit("500",this);
+    QHBoxLayout* hResolutionLayout = new QHBoxLayout();
+    hResolutionLayout->addWidget(editResolution);
+
+
+    //裁剪尺寸,单位像素
+    editCropperFixedWidth = new QLineEdit(this);
+    editCropperFixedHeight = new QLineEdit(this);
+    QHBoxLayout* hCropperFixedSizeLayout = new QHBoxLayout();
+    hCropperFixedSizeLayout->addWidget(editCropperFixedWidth);
+    hCropperFixedSizeLayout->addWidget(editCropperFixedHeight);
+
+    editCropperMinWidth = new QLineEdit("8", this);
+    editCropperMinHeight = new QLineEdit("8", this);
+    QHBoxLayout* hCropperMinSizeLayout = new QHBoxLayout();
+    hCropperMinSizeLayout->addWidget(editCropperMinWidth);
+    hCropperMinSizeLayout->addWidget(editCropperMinHeight);
+
+    //裁剪尺寸,单位厘米
+    editFixedWidth = new QLineEdit(this);
+    editFixedHeight = new QLineEdit(this);
+    QHBoxLayout* hFixedSizeLayout = new QHBoxLayout();
+    hFixedSizeLayout->addWidget(editFixedWidth);
+    hFixedSizeLayout->addWidget(editFixedHeight);
+
+    checkEnableOpacity = new QCheckBox(this);
+    sliderOpacity = new QSlider(Qt::Horizontal, this);
+
+    checkShowDragSquare = new QCheckBox(this);
+    editDragSquareEdge = new QLineEdit("8", this);
+    checkShowRectBorder = new QCheckBox(this);
+
+    labelRectBorderColor = new QLabel(this);
+    btnChooseRectBorderCorlor = new QPushButton(this);
+    QHBoxLayout* hRectBorderColorLayout = new QHBoxLayout();
+    hRectBorderColorLayout->addWidget(labelRectBorderColor);
+    hRectBorderColorLayout->addWidget(btnChooseRectBorderCorlor);
+
+    labelDragSquareColor = new QLabel(this);
+    btnChooseDragSquareColor = new QPushButton(this);
+    QHBoxLayout* hDragSquareColorLayout = new QHBoxLayout();
+    hDragSquareColorLayout->addWidget(labelDragSquareColor);
+    hDragSquareColorLayout->addWidget(btnChooseDragSquareColor);
+
+    QFormLayout* formLayout1 = new QFormLayout();
+    formLayout1->addRow(new QLabel("预览:"), labelPreviewImage);
+    formLayout1->addRow(new QLabel("原图路径:", this), hOriginalImagePathLayout);
+    formLayout1->addRow(new QLabel("输出形状:", this), comboOutputShape);
+    formLayout1->addRow(new QLabel("裁剪形状:", this), comboCropperShape);
+    formLayout1->addRow(new QLabel("分辨率:", this), hResolutionLayout);
+    formLayout1->addRow(new QLabel("像素尺寸:", this), hCropperFixedSizeLayout);
+    formLayout1->addRow(new QLabel("厘米尺寸:", this), hFixedSizeLayout);
+    formLayout1->addRow(new QLabel("最小尺寸:", this), hCropperMinSizeLayout);
+
+    QFormLayout* formLayout2 = new QFormLayout();
+    formLayout2->addRow(new QLabel("透明度:", this), checkEnableOpacity);
+    formLayout2->addRow(new QLabel("透明度:", this), sliderOpacity);
+
+    QFormLayout* formLayout3 = new QFormLayout();
+    formLayout3->addRow(new QLabel("显示拖拽方框:", this), checkShowDragSquare);
+    formLayout3->addRow(new QLabel("拖拽方框尺寸:", this), editDragSquareEdge);
+    formLayout3->addRow(new QLabel("拖拽方框颜色:", this), hDragSquareColorLayout);
+
+    QFormLayout* formLayout4 = new QFormLayout();
+    formLayout4->addRow(new QLabel("显示边框:", this), checkShowRectBorder);
+    formLayout4->addRow(new QLabel("边框颜色:", this), hRectBorderColorLayout);
+
+    btnSavePreview = new QPushButton("保存", this);
+    btnQuit = new QPushButton("退出", this);
+    QHBoxLayout* btnLayout = new QHBoxLayout();
+    btnLayout->addStretch();
+    btnLayout->addWidget(btnSavePreview);
+    btnLayout->addStretch();
+    btnLayout->addWidget(btnQuit);
+    btnLayout->addStretch();
+
+    QVBoxLayout* vLayout = new QVBoxLayout();
+    vLayout->addLayout(formLayout1);
+    vLayout->addStretch();
+    vLayout->addLayout(formLayout2);
+    vLayout->addStretch();
+    vLayout->addLayout(formLayout3);
+    vLayout->addStretch();
+    vLayout->addLayout(formLayout4);
+    vLayout->addStretch();
+    vLayout->addLayout(btnLayout);
+
+    mainLayout = new QHBoxLayout(this);
+    mainLayout->addWidget(imgCropperLabel);
+    mainLayout->addLayout(vLayout);
+}
+
+void ImageCropperDemo::init() {
+    imgCropperLabel->setRectCropper();
+    editCropperFixedWidth->setEnabled(false);
+    editCropperFixedHeight->setEnabled(false);
+    editFixedWidth->setEnabled(false);
+    editFixedHeight->setEnabled(false);
+
+    labelPreviewImage->setFixedSize(96, 96);
+    labelPreviewImage->setAlignment(Qt::AlignCenter);
+    labelPreviewImage->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+    connect(imgCropperLabel, &ImageCropperLabel::croppedImageChanged,
+            this, &ImageCropperDemo::onUpdatePreview);
+
+    btnChooseOriginalImagePath->setIcon(QIcon(":/new/prefix1/images/select-file.ico"));
+    btnChooseOriginalImagePath->setFixedWidth(30);
+    connect(btnChooseOriginalImagePath, &QPushButton::clicked,
+            this, &ImageCropperDemo::onChooseOriginalImage);
+
+    comboOutputShape->addItem("矩形/长方形");
+    comboOutputShape->addItem("椭圆/圆");
+    connect(comboOutputShape, SIGNAL(currentIndexChanged(int)),
+            this, SLOT(onOutputShapeChanged(int)));
+
+    comboCropperShape->addItem("矩形");
+    comboCropperShape->addItem("正方形");
+    comboCropperShape->addItem("固定矩形尺寸");
+    comboCropperShape->addItem("椭圆");
+    comboCropperShape->addItem("圆");
+    comboCropperShape->addItem("固定椭圆尺寸");
+    connect(comboCropperShape, SIGNAL(currentIndexChanged(int)),
+            this, SLOT(onCropperShapeChanged(int)));
+
+    connect(editCropperFixedWidth, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onFixedWidthChanged);
+    connect(editCropperFixedHeight, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onFixedHeightChanged);
+    connect(editFixedWidth, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onWidthChanged);
+    connect(editFixedHeight, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onHeightChanged);
+    connect(editCropperMinWidth, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onMinWidthChanged);
+    connect(editCropperMinHeight, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onMinHeightChanged);
+
+    checkEnableOpacity->setCheckState(Qt::Checked);
+    imgCropperLabel->enableOpacity(true);
+    connect(checkEnableOpacity, &QCheckBox::stateChanged,
+            this, &ImageCropperDemo::onEnableOpacityChanged);
+
+    checkShowDragSquare->setCheckState(Qt::Checked);
+    imgCropperLabel->setShowDragSquare(true);
+    connect(checkShowDragSquare, &QCheckBox::stateChanged,
+            this, &ImageCropperDemo::onShowDragSquareChanged);
+    connect(editDragSquareEdge, &QLineEdit::textChanged,
+            this, &ImageCropperDemo::onDragSquareEdgeChanged);
+
+    sliderOpacity->setRange(0, 100);
+    sliderOpacity->setValue(60);
+    connect(sliderOpacity, &QSlider::valueChanged,
+            this, &ImageCropperDemo::onOpacityChanged);
+
+    checkShowRectBorder->setCheckState(Qt::Checked);
+    connect(checkShowRectBorder, &QCheckBox::stateChanged,
+            this, &ImageCropperDemo::onShowRectBorder);
+
+    setLabelColor(labelRectBorderColor, Qt::white);
+    btnChooseRectBorderCorlor->setIcon(QIcon(":/new/prefix1/images/color-palette.ico"));
+    btnChooseRectBorderCorlor->setFixedWidth(40);
+    connect(btnChooseRectBorderCorlor, &QPushButton::clicked,
+            this, &ImageCropperDemo::onChooseRectBorderColor);
+
+    setLabelColor(labelDragSquareColor, Qt::white);
+    btnChooseDragSquareColor->setIcon(QIcon(":/new/prefix1/images/color-palette.ico"));
+    btnChooseDragSquareColor->setFixedWidth(40);
+    connect(btnChooseDragSquareColor, &QPushButton::clicked,
+            this, &ImageCropperDemo::onChooseDragSquareColor);
+
+    connect(btnSavePreview, &QPushButton::clicked,
+            this, &ImageCropperDemo::onSaveCroppedImage);
+    connect(btnQuit, &QPushButton::clicked,
+            this, &ImageCropperDemo::close);
+
+    imgCropperLabel->update();
+}
+
+
+/*****************************************************************************
+ *
+ *    slots
+ *
+*****************************************************************************/
+
+void ImageCropperDemo::onChooseOriginalImage() {
+    QString filename = QFileDialog::getOpenFileName(this, "选择图片", "",
+                                                    "picture (*.jpg *.png *.bmp *.jpeg)");
+    if (filename.isNull())
+        return;
+
+    QPixmap pixmap;
+    if (!pixmap.load(filename)) {
+        QMessageBox::critical(this, "Error", "加载图片失败!", QMessageBox::Ok);
+        return;
+    }
+
+    editOriginalImagePath->setText(filename);
+    imgCropperLabel->setOriginalImage(pixmap);
+    imgCropperLabel->update();
+    onUpdatePreview();
+    labelPreviewImage->setFrameStyle(0);
+}
+
+void ImageCropperDemo::onOutputShapeChanged(int idx) {
+    // Output: Rectangular
+    if (idx == 0)
+        imgCropperLabel->setOutputShape(OutputShape::RECT);
+    else
+        imgCropperLabel->setOutputShape(OutputShape::ELLIPSE);
+    onUpdatePreview();
+}
+
+void ImageCropperDemo::onCropperShapeChanged(int idx) {
+    switch (CropperShape(idx + 1)) {
+    case CropperShape::RECT: {
+        imgCropperLabel->setRectCropper();
+        editCropperFixedWidth->setEnabled(false);
+        editCropperFixedHeight->setEnabled(false);
+        editFixedWidth->setEnabled(false);
+        editFixedHeight->setEnabled(false);
+        editCropperMinWidth->setEnabled(true);
+        editCropperMinHeight->setEnabled(true);
+        checkShowDragSquare->setEnabled(true);
+        editDragSquareEdge->setEnabled(true);
+        btnChooseDragSquareColor->setEnabled(true);
+        break;
+    }
+    case CropperShape::SQUARE: {
+        imgCropperLabel->setSquareCropper();
+        editCropperFixedWidth->setEnabled(false);
+        editCropperFixedHeight->setEnabled(false);
+        editFixedWidth->setEnabled(false);
+        editFixedHeight->setEnabled(false);
+        editCropperMinWidth->setEnabled(true);
+        editCropperMinHeight->setEnabled(true);
+        checkShowDragSquare->setEnabled(true);
+        editDragSquareEdge->setEnabled(true);
+        btnChooseDragSquareColor->setEnabled(true);
+        break;
+    }
+    case CropperShape::FIXED_RECT: {
+        imgCropperLabel->setFixedRectCropper(QSize(64, 64));
+        editCropperFixedWidth->setEnabled(true);
+        editCropperFixedHeight->setEnabled(true);
+        editFixedWidth->setEnabled(true);
+        editFixedHeight->setEnabled(true);
+        editCropperMinWidth->setEnabled(false);
+        editCropperMinHeight->setEnabled(false);
+        editCropperFixedWidth->setText("64");
+        editCropperFixedHeight->setText("64");
+        checkShowDragSquare->setEnabled(false);
+        editDragSquareEdge->setEnabled(false);
+        btnChooseDragSquareColor->setEnabled(false);
+        break;
+    }
+    case CropperShape::ELLIPSE: {
+        imgCropperLabel->setEllipseCropper();
+        editCropperFixedWidth->setEnabled(false);
+        editCropperFixedHeight->setEnabled(false);
+        editFixedWidth->setEnabled(false);
+        editFixedHeight->setEnabled(false);
+        editCropperMinWidth->setEnabled(true);
+        editCropperMinHeight->setEnabled(true);
+        checkShowDragSquare->setEnabled(true);
+        editDragSquareEdge->setEnabled(true);
+        btnChooseDragSquareColor->setEnabled(true);
+        break;
+    }
+    case CropperShape::CIRCLE: {
+        imgCropperLabel->setCircleCropper();
+        editCropperFixedWidth->setEnabled(false);
+        editCropperFixedHeight->setEnabled(false);
+        editFixedWidth->setEnabled(false);
+        editFixedHeight->setEnabled(false);
+        editCropperMinWidth->setEnabled(true);
+        editCropperMinHeight->setEnabled(true);
+        checkShowDragSquare->setEnabled(true);
+        editDragSquareEdge->setEnabled(true);
+        btnChooseDragSquareColor->setEnabled(true);
+        break;
+    }
+    case CropperShape::FIXED_ELLIPSE:
+        imgCropperLabel->setFixedEllipseCropper(QSize(64, 64));
+        editCropperFixedWidth->setEnabled(true);
+        editCropperFixedHeight->setEnabled(true);
+        editFixedWidth->setEnabled(true);
+        editFixedHeight->setEnabled(true);
+        editCropperMinWidth->setEnabled(false);
+        editCropperMinHeight->setEnabled(false);
+        editCropperFixedWidth->setText("64");
+        editCropperFixedHeight->setText("64");
+        checkShowDragSquare->setEnabled(false);
+        editDragSquareEdge->setEnabled(false);
+        btnChooseDragSquareColor->setEnabled(false);
+        break;
+    case CropperShape::UNDEFINED:
+        break;
+    }
+
+    imgCropperLabel->update();
+    onUpdatePreview();
+}
+
+void ImageCropperDemo::onEnableOpacityChanged(int state) {
+    if (state == Qt::Checked) {
+        sliderOpacity->setEnabled(true);
+        imgCropperLabel->enableOpacity(true);
+    }
+    else {
+        sliderOpacity->setEnabled(false);
+        imgCropperLabel->enableOpacity(false);
+    }
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onShowDragSquareChanged(int state) {
+    if (state == Qt::Checked) {
+        editDragSquareEdge->setEnabled(true);
+        btnChooseDragSquareColor->setEnabled(true);
+        imgCropperLabel->setShowDragSquare(true);
+    }
+    else {
+        editDragSquareEdge->setEnabled(false);
+        btnChooseDragSquareColor->setEnabled(false);
+        imgCropperLabel->setShowDragSquare(false);
+    }
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onDragSquareEdgeChanged(QString edge) {
+    imgCropperLabel->setDragSquareEdge(edge.toInt());
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onOpacityChanged(int val) {
+    imgCropperLabel->setOpacity(val / 100.0);
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onFixedWidthChanged(QString width) {
+    if(editCropperFixedWidth->hasFocus()){
+        int dpi=editResolution->text().toInt();//获取分辨率
+        double cm=width.toDouble()/dpi*2.54;
+        editFixedWidth->setText(QString::number(cm,'f',1));
+    }
+    imgCropperLabel->setCropperFixedWidth(width.toInt());
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onFixedHeightChanged(QString height) {
+    if(editCropperFixedHeight->hasFocus()){
+        int dpi=editResolution->text().toInt();//获取分辨率
+        int cm=height.toDouble()/dpi*2.54;
+        editFixedHeight->setText(QString::number(cm,10));
+    }
+    imgCropperLabel->setCropperFixedHeight(height.toInt());
+    imgCropperLabel->update();
+}
+
+//厘米宽度事件
+void ImageCropperDemo::onWidthChanged(QString width) {
+    if(editFixedWidth->hasFocus()){
+        int dpi=editResolution->text().toInt();//获取分辨率
+        int px=width.toDouble()*dpi/2.54;
+        editCropperFixedWidth->setText(QString::number(px,10));
+    }
+    //    imgCropperLabel->setCropperFixedWidth(width.toInt());
+    //    imgCropperLabel->update();
+}
+
+//厘米高度事件
+void ImageCropperDemo::onHeightChanged(QString height) {
+    if(editFixedHeight->hasFocus()){
+        int dpi=editResolution->text().toInt();//获取分辨率
+        int px=height.toDouble()*dpi/2.54;
+        editCropperFixedHeight->setText(QString::number(px,10));
+    }
+    //    imgCropperLabel->setCropperFixedHeight(height.toInt());
+    //    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onMinWidthChanged(QString width) {
+    imgCropperLabel->setCropperMinimumWidth(width.toInt());
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onMinHeightChanged(QString height) {
+    imgCropperLabel->setMinimumHeight(height.toInt());
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onShowRectBorder(int state) {
+    if (state == Qt::Checked) {
+        btnChooseRectBorderCorlor->setEnabled(true);
+        imgCropperLabel->setShowRectBorder(true);
+    }
+    else {
+        btnChooseRectBorderCorlor->setEnabled(false);
+        imgCropperLabel->setShowRectBorder(false);
+    }
+    imgCropperLabel->update();
+}
+
+void ImageCropperDemo::onChooseRectBorderColor() {
+    QColor color = QColorDialog::getColor(imgCropperLabel->getBorderPen().color(), this);
+    if (color.isValid()) {
+        setLabelColor(labelRectBorderColor, color);
+        QPen pen = imgCropperLabel->getBorderPen();
+        pen.setColor(color);
+        imgCropperLabel->setBorderPen(pen);
+        imgCropperLabel->update();
+    }
+}
+
+void ImageCropperDemo::onChooseDragSquareColor() {
+    QColor color = QColorDialog::getColor(Qt::white, this);
+    if (color.isValid()) {
+        setLabelColor(labelDragSquareColor, color);
+        imgCropperLabel->setDragSquareColor(color);
+        imgCropperLabel->update();
+    }
+}
+
+void ImageCropperDemo::onUpdatePreview() {
+    QPixmap preview = imgCropperLabel->getCroppedImage();
+    preview = preview.scaled(labelPreviewImage->width(), labelPreviewImage->height(),
+                             Qt::KeepAspectRatio, Qt::SmoothTransformation);
+    labelPreviewImage->setPixmap(preview);
+}
+
+void ImageCropperDemo::onSaveCroppedImage() {
+    const QPixmap* pixmap = labelPreviewImage->pixmap();
+    if (!pixmap) {
+        QMessageBox::information(this, "Error", "There is no cropped image to save.", QMessageBox::Ok);
+        return ;
+    }
+
+    QString filename = QFileDialog::getSaveFileName(this, "保存图片", "", "picture (*.png)");
+    if (!filename.isNull()) {
+        if (imgCropperLabel->getCroppedImage().save(filename, "PNG"))
+            QMessageBox::information(this, "Prompt", "保存成功!", QMessageBox::Ok);
+        else
+            QMessageBox::information(this, "Error", "保存失败!", QMessageBox::Ok);
+    }
+}
+

+ 91 - 0
imagecropperdemo.h

@@ -0,0 +1,91 @@
+#ifndef TESTIMAGECROPPERLABEL_H
+#define TESTIMAGECROPPERLABEL_H
+
+#include <QObject>
+#include <QDialog>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QComboBox>
+#include <QLineEdit>
+#include <QCheckBox>
+#include <QPushButton>
+#include <QSlider>
+
+#include "imagecropperlabel.h"
+
+class ImageCropperDemo : public QDialog
+{
+    Q_OBJECT
+public:
+    ImageCropperDemo(QWidget* parent = nullptr);
+
+    void setupLayout();
+
+    void init();
+
+public slots:
+    void onOutputShapeChanged(int idx);
+    void onCropperShapeChanged(int idx);
+    void onEnableOpacityChanged(int state);
+    void onShowDragSquareChanged(int state);
+    void onDragSquareEdgeChanged(QString edge);
+    void onOpacityChanged(int val);
+    void onFixedWidthChanged(QString width);
+    void onFixedHeightChanged(QString height);
+    void onWidthChanged(QString width);//厘米宽度改变事件
+    void onHeightChanged(QString height);//厘米高度改变事件
+    void onMinWidthChanged(QString width);
+    void onMinHeightChanged(QString height);
+    void onShowRectBorder(int state);
+    void onChooseRectBorderColor();
+    void onChooseDragSquareColor();
+
+    void onChooseOriginalImage();
+    void onUpdatePreview();
+    void onSaveCroppedImage();
+
+private:
+    void setLabelColor(QLabel* label, QColor color) {
+        QPixmap pixmap(QSize(80, 25));
+        pixmap.fill(color);
+        label->setPixmap(pixmap);
+    }
+
+private:
+    ImageCropperLabel* imgCropperLabel;
+    QHBoxLayout* mainLayout;
+
+    QLabel* labelPreviewImage;
+
+    QComboBox* comboOutputShape;
+    QComboBox* comboCropperShape;
+
+    QLineEdit* editOriginalImagePath;
+    QPushButton* btnChooseOriginalImagePath;
+
+    QLineEdit* editCropperFixedWidth;//固定尺寸宽度,单位像素
+    QLineEdit* editCropperFixedHeight;//固定尺寸高度,单位像素
+    QLineEdit* editCropperMinWidth;
+    QLineEdit* editCropperMinHeight;
+    QLineEdit* editResolution;//设置图片分辨率
+    QLineEdit* editFixedWidth;//固定尺寸宽度,单位厘米
+    QLineEdit* editFixedHeight;//固定尺寸高度,单位厘米
+
+
+    QCheckBox* checkShowDragSquare;
+    QCheckBox* checkEnableOpacity;
+    QSlider* sliderOpacity;
+    QLineEdit* editDragSquareEdge;
+
+    QCheckBox* checkShowRectBorder;
+    QLabel* labelRectBorderColor;
+    QPushButton* btnChooseRectBorderCorlor;
+
+    QLabel* labelDragSquareColor;
+    QPushButton* btnChooseDragSquareColor;
+
+    QPushButton* btnSavePreview;
+    QPushButton* btnQuit;
+};
+
+#endif // TESTIMAGECROPPERLABEL_H

+ 99 - 0
imagecropperdialog.h

@@ -0,0 +1,99 @@
+#ifndef IMAGECROPPER_H
+#define IMAGECROPPER_H
+
+#include <QWidget>
+#include <QDialog>
+#include <QPainter>
+#include <QLabel>
+#include <QPixmap>
+#include <QString>
+#include <QMessageBox>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QPushButton>
+
+#include "imagecropperlabel.h"
+
+/*******************************************************
+ *  Loacl private class, which do image-cropping
+ *  Used in class ImageCropper
+*******************************************************/
+class ImageCropperDialogPrivate : public QDialog {
+    Q_OBJECT
+public:
+    ImageCropperDialogPrivate(const QPixmap& imageIn, QPixmap& outputImage,
+                              int windowWidth, int windowHeight,
+                              CropperShape shape, QSize cropperSize = QSize()) :
+        QDialog(nullptr),  outputImage(outputImage)
+    {
+        this->setAttribute(Qt::WA_DeleteOnClose, true);
+        this->setWindowTitle("Image Cropper");
+        this->setMouseTracking(true);
+        this->setModal(true);
+
+        imageLabel = new ImageCropperLabel(windowWidth, windowHeight, this);
+        imageLabel->setCropper(shape, cropperSize);
+        imageLabel->setOutputShape(OutputShape::RECT);
+        imageLabel->setOriginalImage(imageIn);
+        imageLabel->enableOpacity(true);
+
+        QHBoxLayout* btnLayout = new QHBoxLayout();
+        btnOk = new QPushButton("OK", this);
+        btnCancel = new QPushButton("Cancel", this);
+        btnLayout->addStretch();
+        btnLayout->addWidget(btnOk);
+        btnLayout->addWidget(btnCancel);
+
+        QVBoxLayout* mainLayout = new QVBoxLayout(this);
+        mainLayout->addWidget(imageLabel);
+        mainLayout->addLayout(btnLayout);
+
+        connect(btnOk, &QPushButton::clicked, this, [this](){
+            this->outputImage = this->imageLabel->getCroppedImage();
+            this->close();
+        });
+        connect(btnCancel, &QPushButton::clicked, this, [this](){
+            this->outputImage = QPixmap();
+            this->close();
+        });
+    }
+
+private:
+    ImageCropperLabel* imageLabel;
+    QPushButton* btnOk;
+    QPushButton* btnCancel;
+    QPixmap& outputImage;
+};
+
+
+/*******************************************************************
+ *  class ImageCropperDialog
+ *      create a instane of class ImageCropperDialogPrivate
+ *      and get cropped image from the instance(after closing)
+********************************************************************/
+class ImageCropperDialog : QObject {
+public:
+    static QPixmap getCroppedImage(const QString& filename,int windowWidth, int windowHeight,
+                                   CropperShape cropperShape, QSize crooperSize = QSize())
+    {
+        QPixmap inputImage;
+        QPixmap outputImage;
+
+        if (!inputImage.load(filename)) {
+            QMessageBox::critical(nullptr, "Error", "Load image failed!", QMessageBox::Ok);
+            return outputImage;
+        }
+
+        ImageCropperDialogPrivate* imageCropperDo =
+            new ImageCropperDialogPrivate(inputImage, outputImage,
+                                          windowWidth, windowHeight,
+                                          cropperShape, crooperSize);
+        imageCropperDo->exec();
+
+        return outputImage;
+    }
+};
+
+
+
+#endif // IMAGECROPPER_H

+ 714 - 0
imagecropperlabel.cpp

@@ -0,0 +1,714 @@
+#include "imagecropperlabel.h"
+
+#include <QPainter>
+#include <QPainterPath>
+#include <QMouseEvent>
+#include <QDebug>
+#include <QBitmap>
+
+ImageCropperLabel::ImageCropperLabel(int width, int height, QWidget* parent) :
+         QLabel(parent)
+{
+    this->setFixedSize(width, height);
+    this->setAlignment(Qt::AlignCenter);
+    this->setMouseTracking(true);
+
+    borderPen.setWidth(1);
+    borderPen.setColor(Qt::white);
+    borderPen.setDashPattern(QVector<qreal>() << 3 << 3 << 3 << 3);
+}
+
+void ImageCropperLabel::setOriginalImage(const QPixmap &pixmap) {
+    originalImage = pixmap;
+
+    int imgWidth = pixmap.width();
+    int imgHeight = pixmap.height();
+    int labelWidth = this->width();
+    int labelHeight = this->height();
+    int imgWidthInLabel;
+    int imgHeightInLabel;
+
+    if (imgWidth * labelHeight < imgHeight * labelWidth) {
+        scaledRate = labelHeight / double(imgHeight);
+        imgHeightInLabel = labelHeight;
+        imgWidthInLabel = int(scaledRate * imgWidth);
+        imageRect.setRect((labelWidth - imgWidthInLabel) / 2, 0,
+                          imgWidthInLabel, imgHeightInLabel);
+    }
+    else {
+        scaledRate = labelWidth / double(imgWidth);
+        imgWidthInLabel = labelWidth;
+        imgHeightInLabel = int(scaledRate * imgHeight);
+        imageRect.setRect(0, (labelHeight - imgHeightInLabel) / 2,
+                          imgWidthInLabel, imgHeightInLabel);
+    }
+
+    tempImage = originalImage.scaled(imgWidthInLabel, imgHeightInLabel,
+                                     Qt::KeepAspectRatio, Qt::SmoothTransformation);
+    this->setPixmap(tempImage);
+
+    if (cropperShape >= CropperShape::FIXED_RECT) {
+        cropperRect.setWidth(int(cropperRect_.width() * scaledRate));
+        cropperRect.setHeight(int(cropperRect_.height() * scaledRate));
+    }
+    resetCropperPos();
+}
+
+
+/*****************************************
+ * set cropper's shape (and size)
+*****************************************/
+void ImageCropperLabel::setRectCropper() {
+    cropperShape = CropperShape::RECT;
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setSquareCropper() {
+    cropperShape = CropperShape::SQUARE;
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setEllipseCropper() {
+    cropperShape = CropperShape::ELLIPSE;
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setCircleCropper() {
+    cropperShape = CropperShape::CIRCLE;
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setFixedRectCropper(QSize size) {
+    cropperShape = CropperShape::FIXED_RECT;
+    cropperRect_.setSize(size);
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setFixedEllipseCropper(QSize size) {
+    cropperShape = CropperShape::FIXED_ELLIPSE;
+    cropperRect_.setSize(size);
+    resetCropperPos();
+}
+
+// not recommended
+void ImageCropperLabel::setCropper(CropperShape shape, QSize size) {
+    cropperShape = shape;
+    cropperRect_.setSize(size);
+    resetCropperPos();
+}
+
+/*****************************************************************************
+     * Set cropper's fixed size
+    *****************************************************************************/
+void ImageCropperLabel::setCropperFixedSize(int fixedWidth, int fixedHeight) {
+    cropperRect_.setSize(QSize(fixedWidth, fixedHeight));
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setCropperFixedWidth(int fixedWidth) {
+    cropperRect_.setWidth(fixedWidth);
+    resetCropperPos();
+}
+
+void ImageCropperLabel::setCropperFixedHeight(int fixedHeight) {
+    cropperRect_.setHeight(fixedHeight);
+    resetCropperPos();
+}
+
+/**********************************************
+ * Move cropper to the center of the image
+ * And resize to default
+**********************************************/
+void ImageCropperLabel::resetCropperPos() {
+    int labelWidth = this->width();
+    int labelHeight = this->height();
+
+    if (cropperShape == CropperShape::FIXED_RECT || cropperShape == CropperShape::FIXED_ELLIPSE) {
+        cropperRect.setWidth(int(cropperRect_.width() * scaledRate));
+        cropperRect.setHeight(int(cropperRect_.height() * scaledRate));
+    }
+
+    switch (cropperShape) {
+        case CropperShape::UNDEFINED:
+            break;
+        case CropperShape::FIXED_RECT:
+        case CropperShape::FIXED_ELLIPSE: {
+            cropperRect.setRect((labelWidth - cropperRect.width()) / 2,
+                             (labelHeight - cropperRect.height()) / 2,
+                             cropperRect.width(), cropperRect.height());
+            break;
+        }
+        case CropperShape::RECT:
+        case CropperShape::SQUARE:
+        case CropperShape::ELLIPSE:
+        case CropperShape::CIRCLE: {
+            int imgWidth = tempImage.width();
+            int imgHeight = tempImage.height();
+            int edge = int((imgWidth > imgHeight ? imgHeight : imgWidth) * 3 / 4.0);
+            cropperRect.setRect((labelWidth - edge) / 2, (labelHeight - edge) / 2, edge, edge);
+            break;
+        }
+    }
+}
+
+QPixmap ImageCropperLabel::getCroppedImage() {
+    return getCroppedImage(this->outputShape);
+}
+
+QPixmap ImageCropperLabel::getCroppedImage(OutputShape shape) {
+    int startX = int((cropperRect.left() - imageRect.left()) / scaledRate);
+    int startY = int((cropperRect.top() - imageRect.top()) / scaledRate);
+    int croppedWidth = int(cropperRect.width() / scaledRate);
+    int croppedHeight = int(cropperRect.height() / scaledRate);
+
+    QPixmap resultImage(croppedWidth, croppedHeight);
+    resultImage = originalImage.copy(startX, startY, croppedWidth, croppedHeight);
+
+    // Set ellipse mask (cut to ellipse shape)
+    if (shape == OutputShape::ELLIPSE) {
+        QSize size(croppedWidth, croppedHeight);
+        QBitmap mask(size);
+        QPainter painter(&mask);
+        painter.setRenderHint(QPainter::Antialiasing);
+        painter.setRenderHint(QPainter::SmoothPixmapTransform);
+        painter.fillRect(0, 0, size.width(), size.height(), Qt::white);
+        painter.setBrush(QColor(0, 0, 0));
+        painter.drawRoundRect(0, 0, size.width(), size.height(), 99, 99);
+        resultImage.setMask(mask);
+    }
+
+    return resultImage;
+}
+
+
+void ImageCropperLabel::paintEvent(QPaintEvent *event) {
+    // Draw original image
+    QLabel::paintEvent(event);
+
+    // Draw cropper and set some effects
+    switch (cropperShape) {
+        case CropperShape::UNDEFINED:
+            break;
+        case CropperShape::FIXED_RECT:
+            drawRectOpacity();
+            break;
+        case CropperShape::FIXED_ELLIPSE:
+            drawEllipseOpacity();
+            break;
+        case CropperShape::RECT:
+            drawRectOpacity();
+            drawSquareEdge(!ONLY_FOUR_CORNERS);
+            break;
+        case CropperShape::SQUARE:
+            drawRectOpacity();
+            drawSquareEdge(ONLY_FOUR_CORNERS);
+            break;
+        case CropperShape::ELLIPSE:
+            drawEllipseOpacity();
+            drawSquareEdge(!ONLY_FOUR_CORNERS);
+            break;
+        case CropperShape::CIRCLE:
+            drawEllipseOpacity();
+            drawSquareEdge(ONLY_FOUR_CORNERS);
+            break;
+    }
+
+    // Draw cropper rect
+    if (isShowRectBorder) {
+        QPainter painter(this);
+        painter.setPen(borderPen);
+        painter.drawRect(cropperRect);
+    }
+}
+
+void ImageCropperLabel::drawSquareEdge(bool onlyFourCorners) {
+    if (!isShowDragSquare)
+        return;
+
+    // Four corners
+    drawFillRect(cropperRect.topLeft(), dragSquareEdge, dragSquareColor);
+    drawFillRect(cropperRect.topRight(), dragSquareEdge, dragSquareColor);
+    drawFillRect(cropperRect.bottomLeft(), dragSquareEdge, dragSquareColor);
+    drawFillRect(cropperRect.bottomRight(), dragSquareEdge, dragSquareColor);
+
+    // Four edges
+    if (!onlyFourCorners) {
+        int centralX = cropperRect.left() + cropperRect.width() / 2;
+        int centralY = cropperRect.top() + cropperRect.height() / 2;
+        drawFillRect(QPoint(cropperRect.left(), centralY), dragSquareEdge, dragSquareColor);
+        drawFillRect(QPoint(centralX, cropperRect.top()), dragSquareEdge, dragSquareColor);
+        drawFillRect(QPoint(cropperRect.right(), centralY), dragSquareEdge, dragSquareColor);
+        drawFillRect(QPoint(centralX, cropperRect.bottom()), dragSquareEdge, dragSquareColor);
+    }
+}
+
+void ImageCropperLabel::drawFillRect(QPoint centralPoint, int edge, QColor color) {
+    QRect rect(centralPoint.x() - edge / 2, centralPoint.y() - edge / 2, edge, edge);
+    QPainter painter(this);
+    painter.fillRect(rect, color);
+}
+
+// Opacity effect
+void ImageCropperLabel::drawOpacity(const QPainterPath& path) {
+    QPainter painterOpac(this);
+    painterOpac.setOpacity(opacity);
+    painterOpac.fillPath(path, QBrush(Qt::black));
+}
+
+void ImageCropperLabel::drawRectOpacity() {
+    if (isShowOpacityEffect) {
+        QPainterPath p1, p2, p;
+        p1.addRect(imageRect);
+        p2.addRect(cropperRect);
+        p = p1.subtracted(p2);
+        drawOpacity(p);
+    }
+}
+
+void ImageCropperLabel::drawEllipseOpacity() {
+    if (isShowOpacityEffect) {
+        QPainterPath p1, p2, p;
+        p1.addRect(imageRect);
+        p2.addEllipse(cropperRect);
+        p = p1.subtracted(p2);
+        drawOpacity(p);
+    }
+}
+
+bool ImageCropperLabel::isPosNearDragSquare(const QPoint& pt1, const QPoint& pt2) {
+    return abs(pt1.x() - pt2.x()) * 2 <= dragSquareEdge
+           && abs(pt1.y() - pt2.y()) * 2 <= dragSquareEdge;
+}
+
+int ImageCropperLabel::getPosInCropperRect(const QPoint &pt) {
+    if (isPosNearDragSquare(pt, QPoint(cropperRect.right(), cropperRect.center().y())))
+        return RECT_RIGHT;
+    if (isPosNearDragSquare(pt, cropperRect.bottomRight()))
+        return RECT_BOTTOM_RIGHT;
+    if (isPosNearDragSquare(pt, QPoint(cropperRect.center().x(), cropperRect.bottom())))
+        return RECT_BOTTOM;
+    if (isPosNearDragSquare(pt, cropperRect.bottomLeft()))
+        return RECT_BOTTOM_LEFT;
+    if (isPosNearDragSquare(pt, QPoint(cropperRect.left(), cropperRect.center().y())))
+        return RECT_LEFT;
+    if (isPosNearDragSquare(pt, cropperRect.topLeft()))
+        return RECT_TOP_LEFT;
+    if (isPosNearDragSquare(pt, QPoint(cropperRect.center().x(), cropperRect.top())))
+        return RECT_TOP;
+    if (isPosNearDragSquare(pt, cropperRect.topRight()))
+        return RECT_TOP_RIGHT;
+    if (cropperRect.contains(pt, true))
+        return RECT_INSIDE;
+    return RECT_OUTSIZD;
+}
+
+/*************************************************
+ *
+ *  Change mouse cursor type
+ *      Arrow, SizeHor, SizeVer, etc...
+ *
+*************************************************/
+
+void ImageCropperLabel::changeCursor() {
+    switch (cursorPosInCropperRect) {
+        case RECT_OUTSIZD:
+            setCursor(Qt::ArrowCursor);
+            break;
+        case RECT_BOTTOM_RIGHT: {
+            switch (cropperShape) {
+            case CropperShape::SQUARE:
+            case CropperShape::CIRCLE:
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+                setCursor(Qt::SizeFDiagCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_RIGHT: {
+            switch (cropperShape) {
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+                setCursor(Qt::SizeHorCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_BOTTOM: {
+            switch (cropperShape) {
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+                setCursor(Qt::SizeVerCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_BOTTOM_LEFT: {
+            switch (cropperShape) {
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+            case CropperShape::SQUARE:
+            case CropperShape::CIRCLE:
+                setCursor(Qt::SizeBDiagCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_LEFT: {
+            switch (cropperShape) {
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+                setCursor(Qt::SizeHorCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_TOP_LEFT: {
+            switch (cropperShape) {
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+            case CropperShape::SQUARE:
+            case CropperShape::CIRCLE:
+                setCursor(Qt::SizeFDiagCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_TOP: {
+            switch (cropperShape) {
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+                setCursor(Qt::SizeVerCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_TOP_RIGHT: {
+            switch (cropperShape) {
+            case CropperShape::SQUARE:
+            case CropperShape::CIRCLE:
+            case CropperShape::RECT:
+            case CropperShape::ELLIPSE:
+                setCursor(Qt::SizeBDiagCursor);
+                break;
+            default:
+                break;
+            }
+            break;
+        }
+        case RECT_INSIDE: {
+            setCursor(Qt::SizeAllCursor);
+            break;
+        }
+    }
+}
+
+/*****************************************************
+ *
+ *  Mouse Events
+ *
+*****************************************************/
+
+void ImageCropperLabel::mousePressEvent(QMouseEvent *e) {
+    currPos = lastPos = e->pos();
+    isLButtonPressed = true;
+}
+
+void ImageCropperLabel::mouseMoveEvent(QMouseEvent *e) {
+    currPos = e->pos();
+    if (!isCursorPosCalculated) {
+        cursorPosInCropperRect = getPosInCropperRect(currPos);
+        changeCursor();
+    }
+
+    if (!isLButtonPressed)
+        return;
+    if (!imageRect.contains(currPos))
+        return;
+
+    isCursorPosCalculated = true;
+
+    int xOffset = currPos.x() - lastPos.x();
+    int yOffset = currPos.y() - lastPos.y();
+    lastPos = currPos;
+
+    int disX = 0;
+    int disY = 0;
+
+    // Move cropper
+    switch (cursorPosInCropperRect) {
+        case RECT_OUTSIZD:
+            break;
+        case RECT_BOTTOM_RIGHT: {
+            disX = currPos.x() - cropperRect.left();
+            disY = currPos.y() - cropperRect.top();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                    break;
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    setCursor(Qt::SizeFDiagCursor);
+                    if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) {
+                        if (disX > disY && cropperRect.top() + disX <= imageRect.bottom()) {
+                            cropperRect.setRight(currPos.x());
+                            cropperRect.setBottom(cropperRect.top() + disX);
+                            emit croppedImageChanged();
+                        }
+                        else if (disX <= disY && cropperRect.left() + disY <= imageRect.right()) {
+                            cropperRect.setBottom(currPos.y());
+                            cropperRect.setRight(cropperRect.left() + disY);
+                            emit croppedImageChanged();
+                        }
+                    }
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    setCursor(Qt::SizeFDiagCursor);
+                    if (disX >= cropperMinimumWidth) {
+                        cropperRect.setRight(currPos.x());
+                        emit croppedImageChanged();
+                    }
+                    if (disY >= cropperMinimumHeight) {
+                        cropperRect.setBottom(currPos.y());
+                        emit croppedImageChanged();
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_RIGHT: {
+            disX = currPos.x() - cropperRect.left();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disX >= cropperMinimumWidth) {
+                        cropperRect.setRight(currPos.x());
+                        emit croppedImageChanged();
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_BOTTOM: {
+            disY = currPos.y() - cropperRect.top();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disY >= cropperMinimumHeight) {
+                        cropperRect.setBottom(cropperRect.bottom() + yOffset);
+                        emit croppedImageChanged();
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_BOTTOM_LEFT: {
+            disX = cropperRect.right() - currPos.x();
+            disY = currPos.y() - cropperRect.top();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                    break;
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disX >= cropperMinimumWidth) {
+                        cropperRect.setLeft(currPos.x());
+                        emit croppedImageChanged();
+                    }
+                    if (disY >= cropperMinimumHeight) {
+                        cropperRect.setBottom(currPos.y());
+                        emit croppedImageChanged();
+                    }
+                    break;
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) {
+                        if (disX > disY && cropperRect.top() + disX <= imageRect.bottom()) {
+                            cropperRect.setLeft(currPos.x());
+                            cropperRect.setBottom(cropperRect.top() + disX);
+                            emit croppedImageChanged();
+                        }
+                        else if (disX <= disY && cropperRect.right() - disY >= imageRect.left()) {
+                            cropperRect.setBottom(currPos.y());
+                            cropperRect.setLeft(cropperRect.right() - disY);
+                            emit croppedImageChanged();
+                        }
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_LEFT: {
+            disX = cropperRect.right() - currPos.x();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disX >= cropperMinimumHeight) {
+                        cropperRect.setLeft(cropperRect.left() + xOffset);
+                        emit croppedImageChanged();
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_TOP_LEFT: {
+            disX = cropperRect.right() - currPos.x();
+            disY = cropperRect.bottom() - currPos.y();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disX >= cropperMinimumWidth) {
+                        cropperRect.setLeft(currPos.x());
+                        emit croppedImageChanged();
+                    }
+                    if (disY >= cropperMinimumHeight) {
+                        cropperRect.setTop(currPos.y());
+                        emit croppedImageChanged();
+                    }
+                    break;
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) {
+                        if (disX > disY && cropperRect.bottom() - disX >= imageRect.top()) {
+                            cropperRect.setLeft(currPos.x());
+                            cropperRect.setTop(cropperRect.bottom() - disX);
+                            emit croppedImageChanged();
+                        }
+                        else if (disX <= disY && cropperRect.right() - disY >= imageRect.left()) {
+                            cropperRect.setTop(currPos.y());
+                            cropperRect.setLeft(cropperRect.right() - disY);
+                            emit croppedImageChanged();
+                        }
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_TOP: {
+            disY = cropperRect.bottom() - currPos.y();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disY >= cropperMinimumHeight) {
+                        cropperRect.setTop(cropperRect.top() + yOffset);
+                        emit croppedImageChanged();
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_TOP_RIGHT: {
+            disX = currPos.x() - cropperRect.left();
+            disY = cropperRect.bottom() - currPos.y();
+            switch (cropperShape) {
+                case CropperShape::UNDEFINED:
+                case CropperShape::FIXED_RECT:
+                case CropperShape::FIXED_ELLIPSE:
+                    break;
+                case CropperShape::RECT:
+                case CropperShape::ELLIPSE:
+                    if (disX >= cropperMinimumWidth) {
+                        cropperRect.setRight(currPos.x());
+                        emit croppedImageChanged();
+                    }
+                    if (disY >= cropperMinimumHeight) {
+                        cropperRect.setTop(currPos.y());
+                        emit croppedImageChanged();
+                    }
+                    break;
+                case CropperShape::SQUARE:
+                case CropperShape::CIRCLE:
+                    if (disX >= cropperMinimumWidth && disY >= cropperMinimumHeight) {
+                        if (disX < disY && cropperRect.left() + disY <= imageRect.right()) {
+                            cropperRect.setTop(currPos.y());
+                            cropperRect.setRight(cropperRect.left() + disY);
+                            emit croppedImageChanged();
+                        }
+                        else if (disX >= disY && cropperRect.bottom() - disX >= imageRect.top()) {
+                            cropperRect.setRight(currPos.x());
+                            cropperRect.setTop(cropperRect.bottom() - disX);
+                            emit croppedImageChanged();
+                        }
+                    }
+                    break;
+            }
+            break;
+        }
+        case RECT_INSIDE: {
+            // Make sure the cropperRect is entirely inside the imageRecct
+            if (xOffset > 0) {
+                if (cropperRect.right() + xOffset > imageRect.right())
+                    xOffset = 0;
+            }
+            else if (xOffset < 0) {
+                if (cropperRect.left() + xOffset < imageRect.left())
+                    xOffset = 0;
+            }
+            if (yOffset > 0) {
+                if (cropperRect.bottom() + yOffset > imageRect.bottom())
+                    yOffset = 0;
+            }
+            else if (yOffset < 0) {
+                if (cropperRect.top() + yOffset < imageRect.top())
+                    yOffset = 0;
+            }
+            cropperRect.moveTo(cropperRect.left() + xOffset, cropperRect.top() + yOffset);
+            emit croppedImageChanged();
+        }
+        break;
+    }
+
+    repaint();
+}
+
+void ImageCropperLabel::mouseReleaseEvent(QMouseEvent *) {
+    isLButtonPressed = false;
+    isCursorPosCalculated = false;
+    setCursor(Qt::ArrowCursor);
+}
+

+ 165 - 0
imagecropperlabel.h

@@ -0,0 +1,165 @@
+/*************************************************************************
+ *  class:          ImageCropperLabel
+ *  author:         github@Leopard-C
+ *  email:          leopard.c@outlook.com
+ *  last change:    2020-03-06
+*************************************************************************/
+#ifndef IMAGECROPPERLABEL_H
+#define IMAGECROPPERLABEL_H
+
+#include <QLabel>
+#include <QPixmap>
+#include <QPen>
+
+enum class CropperShape {
+    UNDEFINED     = 0,
+    RECT          = 1,
+    SQUARE        = 2,
+    FIXED_RECT    = 3,
+    ELLIPSE       = 4,
+    CIRCLE        = 5,
+    FIXED_ELLIPSE = 6
+};
+
+enum class OutputShape {
+    RECT    = 0,
+    ELLIPSE = 1
+};
+
+enum class SizeType {
+    fixedSize           = 0,
+    fitToMaxWidth       = 1,
+    fitToMaxHeight      = 2,
+    fitToMaxWidthHeight = 3,
+};
+
+
+class ImageCropperLabel : public QLabel {
+    Q_OBJECT
+public:
+    ImageCropperLabel(int width, int height, QWidget* parent);
+
+    void setOriginalImage(const QPixmap& pixmap);
+    void setOutputShape(OutputShape shape) { outputShape = shape; }
+    QPixmap getCroppedImage();
+    QPixmap getCroppedImage(OutputShape shape);
+
+    /*****************************************
+     * Set cropper's shape
+    *****************************************/
+    void setRectCropper();
+    void setSquareCropper();
+    void setEllipseCropper();
+    void setCircleCropper();
+    void setFixedRectCropper(QSize size);
+    void setFixedEllipseCropper(QSize size);
+    void setCropper(CropperShape shape, QSize size);    // not recommended
+
+    /*****************************************************************************
+     * Set cropper's fixed size
+    *****************************************************************************/
+    void setCropperFixedSize(int fixedWidth, int fixedHeight);
+    void setCropperFixedWidth(int fixedWidht);
+    void setCropperFixedHeight(int fixedHeight);
+
+    /*****************************************************************************
+     * Set cropper's minimum size
+     * default: the twice of minimum of the edge lenght of drag square
+    *****************************************************************************/
+    void setCropperMinimumSize(int minWidth, int minHeight)
+        { cropperMinimumWidth = minWidth; cropperMinimumHeight = minHeight; }
+    void setCropperMinimumWidth(int minWidth) { cropperMinimumWidth = minWidth; }
+    void setCropperMinimumHeight(int minHeight) { cropperMinimumHeight = minHeight; }
+
+    /*************************************************
+     * Set the size, color, visibility of rectangular border
+    *************************************************/
+    void setShowRectBorder(bool show) { isShowRectBorder = show; }
+    QPen getBorderPen() { return borderPen; }
+    void setBorderPen(const QPen& pen) { borderPen = pen; }
+
+    /*************************************************
+     * Set the size, color of drag square
+    *************************************************/
+    void setShowDragSquare(bool show) { isShowDragSquare = show; }
+    void setDragSquareEdge(int edge) { dragSquareEdge = (edge >= 3 ? edge : 3); }
+    void setDragSquareColor(const QColor& color) { dragSquareColor = color; }
+
+    /*****************************************
+     *  Opacity Effect
+    *****************************************/
+    void enableOpacity(bool b = true) { isShowOpacityEffect = b; }
+    void setOpacity(double newOpacity) { opacity = newOpacity; }
+
+signals:
+    void croppedImageChanged();
+
+protected:
+    /*****************************************
+     * Event
+    *****************************************/
+    virtual void paintEvent(QPaintEvent *event) override;
+    virtual void mousePressEvent(QMouseEvent *e) override;
+    virtual void mouseMoveEvent(QMouseEvent *e) override;
+    virtual void mouseReleaseEvent(QMouseEvent *e) override;
+
+private:
+    /***************************************
+     * Draw shapes
+    ***************************************/
+    void drawFillRect(QPoint centralPoint, int edge, QColor color);
+    void drawRectOpacity();
+    void drawEllipseOpacity();
+    void drawOpacity(const QPainterPath& path);     // shadow effect
+    void drawSquareEdge(bool onlyFourCorners);
+
+    /***************************************
+     * Other utility methods
+    ***************************************/
+    int getPosInCropperRect(const QPoint& pt);
+    bool isPosNearDragSquare(const QPoint& pt1, const QPoint& pt2);
+    void resetCropperPos();
+    void changeCursor();
+
+    enum {
+        RECT_OUTSIZD = 0,
+        RECT_INSIDE = 1,
+        RECT_TOP_LEFT, RECT_TOP, RECT_TOP_RIGHT, RECT_RIGHT,
+        RECT_BOTTOM_RIGHT, RECT_BOTTOM, RECT_BOTTOM_LEFT, RECT_LEFT
+    };
+
+    const bool ONLY_FOUR_CORNERS = true;
+
+private:
+    QPixmap originalImage;
+    QPixmap tempImage;
+
+    bool isShowRectBorder = true;
+    QPen borderPen;
+
+    CropperShape cropperShape = CropperShape::UNDEFINED;
+    OutputShape  outputShape  = OutputShape::RECT;
+
+    QRect imageRect;     // the whole image area in the label (not real size)
+    QRect cropperRect;     // a rectangle frame to choose image area (not real size)
+    QRect cropperRect_;     // cropper rect (real size)
+    double scaledRate = 1.0;
+
+    bool isLButtonPressed = false;
+    bool isCursorPosCalculated = false;
+    int  cursorPosInCropperRect = RECT_OUTSIZD;
+    QPoint lastPos;
+    QPoint currPos;
+
+    bool isShowDragSquare = true;
+    int dragSquareEdge = 8;
+    QColor dragSquareColor = Qt::white;
+
+    int cropperMinimumWidth = dragSquareEdge * 2;
+    int cropperMinimumHeight = dragSquareEdge * 2;
+
+    bool isShowOpacityEffect = false;
+    double opacity = 0.6;
+};
+
+#endif // IMAGECROPPERLABEL_H

二進制
images/arrows.ico


二進制
images/backimage.jpg


二進制
images/bohui.png


二進制
images/close.png


二進制
images/color-palette.ico


二進制
images/cursor.ico


二進制
images/delete.ico


二進制
images/delete.png


二進制
images/draw.ico


二進制
images/drawtool.ico


二進制
images/ellipse.ico


二進制
images/expand.png


二進制
images/font.png


二進制
images/ic_click_recording.png


二進制
images/ic_cutover_close.png


二進制
images/ic_drawing_beeline.png


二進制
images/ic_drawing_round.png


二進制
images/ic_drawing_square.png


二進制
images/ic_drawing_triangle.png


二進制
images/ic_enlarge.png


二進制
images/ic_expand.png


二進制
images/ic_gaotu.png


二進制
images/ic_green_correct.png


二進制
images/ic_increase.png


二進制
images/ic_navigation_help.png


二進制
images/ic_next.png


二進制
images/ic_phone.png


二進制
images/ic_previous.png


二進制
images/ic_put away.png


二進制
images/ic_recording_process.png


二進制
images/ic_red_error.png


二進制
images/ic_return.png


二進制
images/ic_shrink.png


二進制
images/ic_sidebar_arrow.png


二進制
images/ic_sidebar_checked.png


二進制
images/ic_sidebar_color.png


二進制
images/ic_sidebar_image.png


二進制
images/ic_sidebar_pencil.png


二進制
images/ic_sidebar_shape.png


二進制
images/ic_sidebar_text.png


二進制
images/ic_sort.png


二進制
images/ic_square_selected.png


二進制
images/ic_square_unselected.png


二進制
images/ic_top bar_narrow.png


二進制
images/ic_turn left.png


二進制
images/ic_turn right.png


+ 23 - 0
images/images.qrc

@@ -0,0 +1,23 @@
+<RCC>
+    <qresource prefix="/">
+        <file>backimage.jpg</file>
+        <file>draw.ico</file>
+        <file>ellipse.ico</file>
+        <file>rect.ico</file>
+        <file>open.ico</file>
+        <file>save.ico</file>
+        <file>line.ico</file>
+        <file>cursor.ico</file>
+        <file>arrows.ico</file>
+        <file>text.ico</file>
+        <file>delete.ico</file>
+        <file>settingpen.ico</file>
+        <file>pixmap.ico</file>
+        <file>zoomdown.ico</file>
+        <file>zoomup.ico</file>
+        <file>drawtool.ico</file>
+        <file>stick.ico</file>
+        <file>rotation.ico</file>
+        <file>polygon.ico</file>
+    </qresource>
+</RCC>

二進制
images/input.png


二進制
images/input_select.png


二進制
images/line.ico


二進制
images/open.ico


二進制
images/open.png


二進制
images/pause.png


二進制
images/pixmap.ico


二進制
images/play.png


部分文件因文件數量過多而無法顯示