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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM