Qt 通过重写QGraphicItem实现绘制、拖动、旋转、缩放椭圆

本例程通过重写了一个类,继承自QGraphicItem,来实现了在qgraphicsScene上绘制、拖动、旋转、缩放椭圆
效果如下:
在这里插入图片描述

核心代码如下:
mygraphicrectitem.h

 1 #ifndef MYGRAPHICRECTITEM_H
 2 #define MYGRAPHICRECTITEM_H
 3 #include <QObject>
 4 #include <QWidget>
 5 #include <QMouseEvent>
 6 #include <QGraphicsScene>
 7 #include <QGraphicsRectItem>
 8 #include <QGraphicsSceneMouseEvent>
 9 #include <QRect>
10 #include <QPainter>
11 #include <QPolygon>
12 #include <QList>
13 #include <QTransform>
14 enum STATE_FLAG{
15     DEFAULT_FLAG=0,
16     MOV_LEFT_LINE,//标记当前为用户按下矩形的左边界区域
17     MOV_TOP_LINE,//标记当前为用户按下矩形的上边界区域
18     MOV_RIGHT_LINE,//标记当前为用户按下矩形的右边界区域
19     MOV_BOTTOM_LINE,//标记当前为用户按下矩形的下边界区域
20     MOV_RIGHTBOTTOM_RECT,//标记当前为用户按下矩形的右下角
21     MOV_RECT,//标记当前为鼠标拖动图片移动状态
22     ROTATE//标记当前为旋转状态
23 };
24 enum SHAPE_TYPE{
25     RECTANGLE=0,
26     CIRCLE
27 };
28 
29 class myGraphicRectItem:public QObject,public QGraphicsItem
30 {
31     Q_OBJECT
32 public:
33     SHAPE_TYPE m_ShapeType;
34     myGraphicRectItem(QGraphicsItem *parent = nullptr);
35     //myGraphicRectItem(QRectF m_OriginRect = QRectF(0,0,100,100));
36     QRectF  boundingRect() const;
37     QPainterPath shape() const;
38     QPainterPath getCollideShape();
39     ~myGraphicRectItem();
40     void setRectSize(QRectF mrect,bool bResetRotateCenter = true);
41     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
42     void mousePressEvent(QGraphicsSceneMouseEvent *event);
43     void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
44     void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
45     void SetRotate(qreal RotateAngle);
46     QPointF getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle);//获取旋转后的点
47     QList<QPointF> getRotatePoints(QPointF ptCenter,QList<QPointF> ptIns,qreal angle);//获取多个旋转后的点
48     QPolygonF getRotatePolygonFromRect(QPointF ptCenter,QRectF rectIn,qreal angle);//将矩形旋转之后返回多边形
49     QRectF getCrtPosRectToSceen();
50     QPolygonF getCrtPolygonToScreen();
51 
52     QPointF getSmallRotateRectCenter(QPointF ptA,QPointF ptB);//获取旋转时候矩形正上方的旋转标记矩形
53     QRectF  getSmallRotateRect(QPointF ptA,QPointF ptB);
54     bool    m_bRotate;
55     qreal   m_RotateAngle;
56     QPointF m_RotateCenter;
57 
58 private:
59     QRectF  m_oldRect;
60     QPolygonF m_oldRectPolygon;
61     QRectF  m_RotateAreaRect;
62     bool    m_bResize;
63     QPolygonF m_insicedPolygon;
64     QRectF  m_insicedRectf;
65     QPolygonF m_leftPolygon;
66     QRectF  m_leftRectf;
67     QPolygonF m_topPolygon;
68     QRectF  m_topRectf;
69     QPolygonF m_rightPolygon;
70     QRectF  m_rightRectf;
71     QPolygonF m_bottomPolygon;
72     QRectF  m_bottomRectf;
73     QRectF m_SmallRotateRect;//矩形顶部用来表示旋转的标记的矩形
74     QPolygonF m_SmallRotatePolygon;//矩形顶部用来表示旋转的标记的矩形旋转后形成的多边形
75 //    QPolygonF m_rbPolygon;
76 //    QRectF  m_rbRectf;
77     QPointF m_startPos;
78     STATE_FLAG m_StateFlag;
79     QPointF *pPointFofSmallRotateRect;
80 protected:
81 
82 };
83 
84 #endif // MYGRAPHICRECTITEM_H

mygraphicrectitem.cpp

  1 #include "mygraphicrectitem.h"
  2 #include <QtMath>
  3 #include <QDebug>
  4 
  5 myGraphicRectItem::myGraphicRectItem(QGraphicsItem *parent):
  6     m_ShapeType(RECTANGLE),
  7     m_bResize(false),
  8     m_oldRect(0,0,100,100),
  9     m_bRotate(false),
 10     m_RotateAngle(0),
 11     m_StateFlag(DEFAULT_FLAG)
 12 {
 13     //setParent(parent);
 14     setRectSize(m_oldRect);
 15     setToolTip("Click and drag me!");  //提示
 16     setCursor(Qt::ArrowCursor);   //改变光标形状,手的形状
 17     setFlag(QGraphicsItem::ItemIsMovable);
 18     pPointFofSmallRotateRect = new QPointF[4];
 19     SetRotate(0);
 20     //setFlag(QGraphicsItem::ItemIsSelectable);//
 21     setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
 22 }
 23 
 24 QRectF myGraphicRectItem::boundingRect() const//用来控制本item绘制区域
 25 {
 26     QPainterPath path;
 27     path.addPolygon(m_oldRectPolygon);
 28     path.addPolygon(m_SmallRotatePolygon);
 29     return path.boundingRect();
 30 }
 31 
 32 QPainterPath myGraphicRectItem::shape() const//用来控制检测碰撞collide和鼠标点击hit响应区域
 33 {
 34     QPainterPath path;
 35     path.addPolygon(m_oldRectPolygon);
 36     path.addPolygon(m_SmallRotatePolygon);
 37     return path;
 38 }
 39 
 40 QPainterPath myGraphicRectItem::getCollideShape()
 41 {
 42     QPainterPath path;
 43     if(m_ShapeType==RECTANGLE)
 44     {
 45         path.addPolygon(m_oldRectPolygon);
 46     }
 47     else if(m_ShapeType == CIRCLE)
 48     {
 49         QPainterPath pathTemp;
 50         pathTemp.addEllipse(m_oldRect);
 51         QTransform trans;
 52         trans.translate(m_RotateCenter.x(),m_RotateCenter.y());
 53         trans.rotate(m_RotateAngle);//QTransform是绕(0,0)点旋转的,所以转之前要先平移到圆心,然后旋转,然后再平移回来
 54         trans.translate(-m_RotateCenter.x(),-m_RotateCenter.y());
 55         path = trans.map(pathTemp);
 56     }
 57     return path;
 58 }
 59 
 60 myGraphicRectItem::~myGraphicRectItem()
 61 {
 62     delete []pPointFofSmallRotateRect;
 63     pPointFofSmallRotateRect = nullptr;
 64 }
 65 
 66 void myGraphicRectItem::setRectSize(QRectF mrect, bool bResetRotateCenter)
 67 {
 68     m_oldRect = mrect;
 69     if(bResetRotateCenter)
 70     {
 71         m_RotateCenter.setX(m_oldRect.x()+m_oldRect.width()/2);
 72         m_RotateCenter.setY(m_oldRect.y()+m_oldRect.height()/2);
 73     }
 74     m_oldRectPolygon = getRotatePolygonFromRect(m_RotateCenter,m_oldRect,m_RotateAngle);
 75 
 76     m_insicedRectf = QRectF(m_oldRect.x()+8,m_oldRect.y()+8,m_oldRect.width()-16,m_oldRect.height()-16);
 77     m_insicedPolygon =getRotatePolygonFromRect(m_RotateCenter,m_insicedRectf,m_RotateAngle);
 78 
 79     m_leftRectf = QRectF(m_oldRect.x(),m_oldRect.y(),8,m_oldRect.height()-8);
 80     m_leftPolygon = getRotatePolygonFromRect(m_RotateCenter,m_leftRectf,m_RotateAngle);
 81 
 82     m_topRectf = QRectF(m_oldRect.x()+8,m_oldRect.y(),m_oldRect.width()-8,8);
 83     m_topPolygon = getRotatePolygonFromRect(m_RotateCenter,m_topRectf,m_RotateAngle);
 84 
 85     m_rightRectf = QRectF(m_oldRect.right()-8,m_oldRect.y()+8,8,m_oldRect.height()-16);
 86     m_rightPolygon = getRotatePolygonFromRect(m_RotateCenter,m_rightRectf,m_RotateAngle);
 87 
 88     m_bottomRectf = QRectF(m_oldRect.x(),m_oldRect.bottom()-8,m_oldRect.width()-8,8);
 89     m_bottomPolygon = getRotatePolygonFromRect(m_RotateCenter,m_bottomRectf,m_RotateAngle);
 90 
 91     m_SmallRotateRect = getSmallRotateRect(mrect.topLeft(),mrect.topRight());//矩形正上方的旋转标记矩形
 92     m_SmallRotatePolygon = getRotatePolygonFromRect(m_RotateCenter,m_SmallRotateRect,m_RotateAngle);
 93 
 94 }
 95 
 96 void myGraphicRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
 97 {
 98     QPen mPen;
 99 //    if(this->isSelected())
100 //    {
101 //        mPen= QPen(Qt::lightGray);
102 //    }
103 //    else
104 //    {
105         mPen= QPen(Qt::yellow);
106 //    }
107     painter->setPen(mPen);
108     if(m_ShapeType == RECTANGLE)
109     {
110         //绘制旋转后的矩形
111         painter->drawPolygon(m_oldRectPolygon);
112         //绘制旋转圆形
113         mPen.setWidth(2);
114         mPen.setColor(Qt::green);
115         painter->setPen(mPen);
116         QPointF pf = getSmallRotateRectCenter(m_oldRectPolygon[0],m_oldRectPolygon[1]);
117         QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);
118         painter->drawEllipse(rect);//绘制圆形
119         painter->drawPoint(pf);//绘制点
120         //有重叠的情况
121         if(!this->scene()->collidingItems(this).isEmpty())
122         {
123            QPainterPath path,pathOthers;
124            QList<QGraphicsItem *> lstcolliItems = this->scene()->collidingItems(this);
125            int nColliNum = lstcolliItems.count();
126            for(int i = 0;i<nColliNum;i++)
127            {
128                myGraphicRectItem* pTempItem = (myGraphicRectItem*)this->scene()->collidingItems(this)[i];
129                if(pTempItem->zValue()==0)
130                {
131                    QPainterPath tempPath = pTempItem->getCollideShape();
132                    tempPath.translate(pTempItem->pos());//转换到view中的坐标
133                    pathOthers += tempPath;//记录与本item重叠的item的路径
134                }
135            }
136            path.addPolygon(m_oldRectPolygon);
137            path.translate(this->pos());//转换到view中的坐标
138            path &= pathOthers;//计算重叠部分的路径path
139            path.translate(-this->pos().x(),-this->pos().y());//转换回本Item中的坐标
140            QBrush brush(Qt::cyan);
141            mPen.setColor(Qt::blue);
142            painter->setPen(mPen);
143            painter->setBrush(brush);
144            painter->drawPath(path);//绘制重叠区域
145         }
146     }
147     else if(m_ShapeType == CIRCLE)
148     {
149 //        //绘制旋转后的矩形
150 //        painter->drawRect(m_oldRect);
151 //        painter->drawPolygon(m_oldRectPolygon);
152         //绘制旋转后的圆形
153         QTransform trans0;
154         QPainterPath path0;
155         trans0.translate(m_RotateCenter.x(),m_RotateCenter.y());
156         trans0.rotate(m_RotateAngle,Qt::ZAxis);
157         trans0.translate(-m_RotateCenter.x(),-m_RotateCenter.y());
158         path0.addEllipse(m_oldRect);
159         path0 = trans0.map(path0);//将pathTemp旋转m_RotateAngle角度
160         painter->drawPath(path0);//drawPolygon(m_oldRectPolygon);
161         //绘制旋转圆形标记
162         mPen.setWidth(2);
163         mPen.setColor(Qt::green);
164         painter->setPen(mPen);
165         QPointF pf = getSmallRotateRectCenter(m_oldRectPolygon[0],m_oldRectPolygon[1]);
166         QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);
167         painter->drawEllipse(rect);//绘制圆形
168         painter->drawPoint(pf);//绘制点
169         //有重叠的情况
170         if(!this->scene()->collidingItems(this).isEmpty())
171         {
172            QPainterPath path,pathOthers;
173            QList<QGraphicsItem *> lstcolliItems = this->scene()->collidingItems(this);
174            int nColliNum = lstcolliItems.count();
175            for(int i = 0;i<nColliNum;i++)
176            {
177                myGraphicRectItem* pTempItem = (myGraphicRectItem*)this->scene()->collidingItems(this)[i];
178                if(pTempItem->zValue()==0)
179                {
180                    QPainterPath tempPath = pTempItem->getCollideShape();
181                    tempPath.translate(pTempItem->pos());//转换到view中的坐标
182                    pathOthers += tempPath;//记录与本item重叠的item的路径
183                }
184            }
185            QTransform trans;
186            //旋转的时候,QTransform是绕坐标轴的(0,0)点旋转的,所以先要平移到坐标轴0,0点,然后的旋转,然后移回到原来的位置
187            trans.translate(m_RotateCenter.x(),m_RotateCenter.y());
188            trans.rotate(m_RotateAngle);
189            trans.translate(-m_RotateCenter.x(),-m_RotateCenter.y());
190            path.addEllipse(m_oldRect);
191            path = trans.map(path);//将pathTemp旋转m_RotateAngle角度
192            path.translate(this->pos());//转换到view中的坐标
193            path &= pathOthers;//计算重叠部分的路径path
194            path.translate(-this->pos().x(),-this->pos().y());//转换回本Item中的坐标
195            QBrush brush(Qt::cyan);
196            mPen.setColor(Qt::blue);
197            painter->setPen(mPen);
198            painter->setBrush(brush);
199            painter->drawPath(path);//绘制重叠区域
200         }
201     }
202 //scene()->update();
203 }
204 
205 void myGraphicRectItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
206 {
207     if(event->button()== Qt::LeftButton)
208     {
209         //setSelected(true);
210         m_startPos = event->pos();//鼠标左击时,获取当前鼠标在图片中的坐标,
211         if(m_SmallRotatePolygon.containsPoint(m_startPos,Qt::WindingFill))//旋转矩形
212         {
213             setCursor(Qt::PointingHandCursor);
214             m_StateFlag = ROTATE;
215         }
216         else if(m_insicedPolygon.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片
217         {
218             setCursor(Qt::ClosedHandCursor);   //改变光标形状,手的形状
219             m_StateFlag = MOV_RECT;//标记当前为鼠标拖动图片移动状态
220         }
221         else if(m_leftPolygon.containsPoint(m_startPos,Qt::WindingFill))
222         {
223             setCursor(Qt::SizeHorCursor);
224             m_StateFlag = MOV_LEFT_LINE;//标记当前为用户按下矩形的左边界区域
225         }
226         else if(m_rightPolygon.containsPoint(m_startPos,Qt::WindingFill))
227         {
228             setCursor(Qt::SizeHorCursor);
229             m_StateFlag = MOV_RIGHT_LINE;//标记当前为用户按下矩形的右边界区域
230         }
231         else if(m_topPolygon.containsPoint(m_startPos,Qt::WindingFill))
232         {
233             setCursor(Qt::SizeVerCursor);
234             m_StateFlag = MOV_TOP_LINE;//标记当前为用户按下矩形的上边界区域
235         }
236         else if(m_bottomPolygon.containsPoint(m_startPos,Qt::WindingFill))
237         {
238             setCursor(Qt::SizeVerCursor);
239             m_StateFlag = MOV_BOTTOM_LINE;//标记当前为用户按下矩形的下边界区域
240         }
241 //        else if(m_rbPolygon.containsPoint(m_startPos,Qt::WindingFill))
242 //        {
243 //            setCursor(Qt::SizeFDiagCursor);
244 //            m_StateFlag = MOV_RIGHTBOTTOM_RECT;//标记当前为用户按下矩形的右下角
245 //        }
246         else
247         {
248             m_StateFlag = DEFAULT_FLAG;
249         }
250     }
251     else
252     {
253         QGraphicsItem::mousePressEvent(event);
254     }
255 }
256 
257 void myGraphicRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
258 {
259     if(m_StateFlag == ROTATE)
260     {
261        int nRotateAngle = atan2((event->pos().x()-m_RotateCenter.x()),(event->pos().y()-m_RotateCenter.y()))*180/M_PI;
262        SetRotate(180-nRotateAngle);       
263        //qDebug()<<nRotateAngle;
264     }
265     else if(m_StateFlag == MOV_RECT)
266     {
267         QPointF point = (event->pos() - m_startPos);
268         moveBy(point.x(), point.y());
269         setRectSize(m_oldRect);
270         scene()->update();
271     }
272     else if(m_StateFlag == MOV_LEFT_LINE)
273     {
274         QPointF pf = QPointF((m_oldRectPolygon.at(1).x()+m_oldRectPolygon.at(2).x())/2,((m_oldRectPolygon.at(1).y()+m_oldRectPolygon.at(2).y())/2));
275         //计算到右侧边中点的距离
276         qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y()));
277         qreal dis2LT = sqrt((event->pos().x()-m_oldRectPolygon.at(0).x())*(event->pos().x()-m_oldRectPolygon.at(0).x()) +(event->pos().y()-m_oldRectPolygon.at(0).y())*(event->pos().y()-m_oldRectPolygon.at(0).y()));
278         qreal dis2RT = sqrt((event->pos().x()-m_oldRectPolygon.at(1).x())*(event->pos().x()-m_oldRectPolygon.at(1).x()) +(event->pos().y()-m_oldRectPolygon.at(1).y())*(event->pos().y()-m_oldRectPolygon.at(1).y()));
279         if(dis<16||dis2LT>dis2RT)
280         {
281             return;
282         }
283         else
284         {
285             QRectF newRect(m_oldRect);
286             newRect.setLeft(m_oldRect.right()-dis);
287             newRect.setRight(m_oldRect.right());
288             setRectSize(newRect,false);
289             m_RotateCenter=QPointF((m_oldRectPolygon.at(0).x()+m_oldRectPolygon.at(2).x())/2,(m_oldRectPolygon.at(0).y()+m_oldRectPolygon.at(2).y())/2);
290             m_oldRect.moveCenter(m_RotateCenter);
291             setRectSize(m_oldRect);
292             scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
293         }
294     }
295     else if(m_StateFlag == MOV_TOP_LINE)
296     {
297         //底边中点
298         QPointF pf = QPointF((m_oldRectPolygon.at(2).x()+m_oldRectPolygon.at(3).x())/2,((m_oldRectPolygon.at(2).y()+m_oldRectPolygon.at(3).y())/2));
299         //计算到底边中点的距离
300         qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y()));
301         qreal dis2LT = sqrt((event->pos().x()-m_oldRectPolygon.at(0).x())*(event->pos().x()-m_oldRectPolygon.at(0).x()) +(event->pos().y()-m_oldRectPolygon.at(0).y())*(event->pos().y()-m_oldRectPolygon.at(0).y()));
302         qreal dis2LB = sqrt((event->pos().x()-m_oldRectPolygon.at(3).x())*(event->pos().x()-m_oldRectPolygon.at(3).x()) +(event->pos().y()-m_oldRectPolygon.at(3).y())*(event->pos().y()-m_oldRectPolygon.at(3).y()));
303         if(dis<16||dis2LT>dis2LB)
304         {
305             return;
306         }
307         else
308         {
309             QRectF newRect(m_oldRect);
310             newRect.setTop(m_oldRect.bottom()-dis);
311             newRect.setBottom(m_oldRect.bottom());
312             setRectSize(newRect,false);
313             m_RotateCenter=QPointF((m_oldRectPolygon.at(0).x()+m_oldRectPolygon.at(2).x())/2,(m_oldRectPolygon.at(0).y()+m_oldRectPolygon.at(2).y())/2);
314             m_oldRect.moveCenter(m_RotateCenter);
315             setRectSize(m_oldRect);
316             scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
317         }
318     }
319     else if(m_StateFlag == MOV_RIGHT_LINE)
320     {
321         QPointF pf = QPointF((m_oldRectPolygon.at(0).x()+m_oldRectPolygon.at(3).x())/2,((m_oldRectPolygon.at(0).y()+m_oldRectPolygon.at(3).y())/2));
322         //计算到左侧边中点的距离
323         qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y()));
324         qreal dis2LT = sqrt((event->pos().x()-m_oldRectPolygon.at(0).x())*(event->pos().x()-m_oldRectPolygon.at(0).x()) +(event->pos().y()-m_oldRectPolygon.at(0).y())*(event->pos().y()-m_oldRectPolygon.at(0).y()));
325         qreal dis2RT = sqrt((event->pos().x()-m_oldRectPolygon.at(1).x())*(event->pos().x()-m_oldRectPolygon.at(1).x()) +(event->pos().y()-m_oldRectPolygon.at(1).y())*(event->pos().y()-m_oldRectPolygon.at(1).y()));
326         if(dis<16||dis2LT<dis2RT)
327         {
328             return;
329         }
330         else
331         {
332             QRectF newRect(m_oldRect);
333             newRect.setLeft(m_oldRect.left());
334             newRect.setRight(m_oldRect.left()+dis);
335             setRectSize(newRect,false);
336             m_RotateCenter=QPointF((m_oldRectPolygon.at(0).x()+m_oldRectPolygon.at(2).x())/2,(m_oldRectPolygon.at(0).y()+m_oldRectPolygon.at(2).y())/2);
337             m_oldRect.moveCenter(m_RotateCenter);
338             setRectSize(m_oldRect);
339             scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
340         }
341     }
342     else if(m_StateFlag == MOV_BOTTOM_LINE)
343     {
344         //顶边中点
345         QPointF pf = QPointF((m_oldRectPolygon.at(0).x()+m_oldRectPolygon.at(1).x())/2,((m_oldRectPolygon.at(0).y()+m_oldRectPolygon.at(1).y())/2));
346         //计算到底边中点的距离
347         qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y()));
348         qreal dis2LT = sqrt((event->pos().x()-m_oldRectPolygon.at(0).x())*(event->pos().x()-m_oldRectPolygon.at(0).x()) +(event->pos().y()-m_oldRectPolygon.at(0).y())*(event->pos().y()-m_oldRectPolygon.at(0).y()));
349         qreal dis2LB = sqrt((event->pos().x()-m_oldRectPolygon.at(3).x())*(event->pos().x()-m_oldRectPolygon.at(3).x()) +(event->pos().y()-m_oldRectPolygon.at(3).y())*(event->pos().y()-m_oldRectPolygon.at(3).y()));
350         if(dis<16||dis2LT<dis2LB)
351         {
352             return;
353         }
354         else
355         {
356             QRectF newRect(m_oldRect);
357             newRect.setTop(m_oldRect.top());
358             newRect.setBottom(m_oldRect.top()+dis);
359             setRectSize(newRect,false);
360             m_RotateCenter=QPointF((m_oldRectPolygon.at(0).x()+m_oldRectPolygon.at(2).x())/2,(m_oldRectPolygon.at(0).y()+m_oldRectPolygon.at(2).y())/2);
361             m_oldRect.moveCenter(m_RotateCenter);
362             setRectSize(m_oldRect);
363             scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
364         }
365     }
366 }
367 
368 void myGraphicRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
369 {
370     setCursor(Qt::ArrowCursor);
371     if(m_StateFlag == MOV_RECT)
372     {
373         m_StateFlag = DEFAULT_FLAG;
374     }
375     else {
376         QGraphicsItem::mouseReleaseEvent(event);
377     }
378 }
379 
380 void myGraphicRectItem::SetRotate(qreal RotateAngle)
381 {
382     m_bRotate = true;
383     m_RotateAngle = RotateAngle;
384     setRectSize(m_oldRect);
385     if(this->scene()!=nullptr)
386         this->scene()->update();
387 }
388 
389 QPointF myGraphicRectItem::getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle)
390 {
391     double dx = ptCenter.x();
392     double dy = ptCenter.y();
393     double x = ptIn.x();
394     double y = ptIn.y();
395     double xx,yy;
396     xx = (x-dx)*cos(angle*M_PI/180)-(y-dy)*sin(angle*M_PI/180)+dx;
397     yy = (x-dx)*sin(angle*M_PI/180)+(y-dy)*cos(angle*M_PI/180)+dy;
398 
399     return QPointF(xx,yy);
400 }
401 
402 QList<QPointF> myGraphicRectItem::getRotatePoints(QPointF ptCenter, QList<QPointF> ptIns, qreal angle)
403 {
404     QList<QPointF> lstPt;
405     for(int i = 0;i<ptIns.count();i++)
406     {
407         lstPt.append(getRotatePoint(ptCenter,ptIns.at(i),angle));
408     }
409     return lstPt;
410 }
411 
412 QPolygonF myGraphicRectItem::getRotatePolygonFromRect(QPointF ptCenter, QRectF rectIn, qreal angle)
413 {
414     QVector<QPointF> vpt;
415     QPointF pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle);
416     vpt.append(pf);
417     pf = getRotatePoint(ptCenter,rectIn.topRight(),angle);
418     vpt.append(pf);
419     pf = getRotatePoint(ptCenter,rectIn.bottomRight(),angle);
420     vpt.append(pf);
421     pf = getRotatePoint(ptCenter,rectIn.bottomLeft(),angle);
422     vpt.append(pf);
423     pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle);
424     vpt.append(pf);
425     return QPolygonF(vpt);
426 }
427 
428 QRectF myGraphicRectItem::getCrtPosRectToSceen()
429 {
430     QRectF retRect = QRectF(m_oldRect.x()+pos().x(),m_oldRect.y()+pos().y(),m_oldRect.width(),m_oldRect.height());
431     return retRect;
432 }
433 
434 QPolygonF myGraphicRectItem::getCrtPolygonToScreen()
435 {
436     QVector<QPointF> vpt;
437     for(int i = 0;i<m_oldRectPolygon.length();i++)
438     {
439         vpt.append(QPointF(m_oldRectPolygon[i].x()+pos().x(),m_oldRectPolygon[i].y()+pos().y()));
440     }
441     return QPolygonF(vpt);
442 }
443 QRectF myGraphicRectItem::getSmallRotateRect(QPointF ptA,QPointF ptB)
444 {
445     QPointF pt = getSmallRotateRectCenter(ptA,ptB);
446     return QRectF(pt.x()-10,pt.y()-10,20,20);
447 }
448 QPointF myGraphicRectItem::getSmallRotateRectCenter(QPointF ptA,QPointF ptB)
449 {
450     QPointF ptCenter = QPointF((ptA.x()+ptB.x())/2,(ptA.y()+ptB.y())/2);//A,B点的中点C
451     //中垂线方程式为 y=x*k + b;
452     qreal x,y;//旋转图标矩形的中心
453     if(abs(ptB.y()-ptA.y())<0.1)
454     {
455         if(ptA.x()<ptB.x())//矩形左上角在上方
456         {
457             x = ptCenter.x();
458             y = ptCenter.y()-20;
459         }
460         else//矩形左上角在下方
461         {
462             x = ptCenter.x();
463             y = ptCenter.y()+20;
464         }
465     }
466     else if(ptB.y()>ptA.y())//顺时针旋转0-180
467     {
468         qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率
469         qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2;
470         //求AB线中垂线上离AB中点20个像素的点C的坐标
471         x = 20*cos(atan(k))+ptCenter.x();
472         y = k*x+b;
473     }
474     else if(ptB.y()<ptA.y())//顺时针旋转180-360
475     {
476         qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率
477         qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2;
478         //求AB线中垂线上离AB中点20个像素的点C的坐标
479         x = -20*cos(atan(k))+ptCenter.x();
480         y = k*x+b;
481     }
482     return QPointF(x,y);
483 }
原文地址:https://www.cnblogs.com/ybqjymy/p/13862407.html