本例程通过重写了一个类,继承自QGraphicItem,来实现了在qgraphicsScene上绘制、拖动、缩放、旋转矩形。
效果如下:
其实要实现绘制、拖动、缩放矩形都不难,难的是在旋转之后还要支持缩放。
我的思路是:
1.实现绘制矩形:只要定义一个全局变量QRectF m_oldRect,在外面矩形大小传进来,然后在paint函数里面绘制这个矩形就行
2.实现拖动矩形:重写mousePressEvent,mouseMoveEvent,mouseReleaseEvent,记录鼠标按下的起始点和移动时候的点,并用moveBy()函数来移动矩形即可
3.实现缩放:在矩形内部靠近4条边的地方定义4个矩形,当鼠标按下的时候在这4个矩形方框内,则将矩形往4个方向拉伸
4.实现旋转:
我给之前定义的矩形全部配一个QPolygonF,因为我只能通过绘制多边形的方式来画出旋转之后的矩形。
矩形正上方的圆圈我是通过三角函数+直线方程来计算,让其始终绘制在矩形左右两个顶点的中垂线上方。
当鼠标落在圆形内部的时候可以控制矩形旋转。
在矩形旋转之后,再进行拉伸的时候,我是通过的计算鼠标的点离对面的边的距离来重新计算矩形的大小,然后计算对应的QPolygonF的大小。
主要代码如下:
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 enum STATE_FLAG{ 14 DEFAULT_FLAG=0, 15 MOV_LEFT_LINE,//标记当前为用户按下矩形的左边界区域
16 MOV_TOP_LINE,//标记当前为用户按下矩形的上边界区域
17 MOV_RIGHT_LINE,//标记当前为用户按下矩形的右边界区域
18 MOV_BOTTOM_LINE,//标记当前为用户按下矩形的下边界区域
19 MOV_RIGHTBOTTOM_RECT,//标记当前为用户按下矩形的右下角
20 MOV_RECT,//标记当前为鼠标拖动图片移动状态
21 ROTATE//标记当前为旋转状态
22 }; 23 class myGraphicRectItem:public QObject,public QGraphicsItem 24 { 25 Q_OBJECT 26 public: 27 myGraphicRectItem(QGraphicsItem *parent = nullptr); 28 //myGraphicRectItem(QRectF m_OriginRect = QRectF(0,0,100,100));
29 QRectF boundingRect() const; 30 ~myGraphicRectItem(); 31 void setRectSize(QRectF mrect,bool bResetRotateCenter = true); 32 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 33 void mousePressEvent(QGraphicsSceneMouseEvent *event); 34 void mouseMoveEvent(QGraphicsSceneMouseEvent *event); 35 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 36 void SetRotate(qreal RotateAngle,QPointF ptCenter=QPointF(-999,-999)); 37 QPointF getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle);//获取旋转后的点
38 QList<QPointF> getRotatePoints(QPointF ptCenter,QList<QPointF> ptIns,qreal angle);//获取多个旋转后的点
39 QPolygonF getRotatePolygonFromRect(QPointF ptCenter,QRectF rectIn,qreal angle);//将矩形旋转之后返回多边形
40 QRectF getCrtPosRectToSceen(); 41 QRectF m_SmallRotateRect;//矩形顶部用来表示旋转的标记的矩形
42 QPolygonF m_SmallRotatePolygon;//矩形顶部用来表示旋转的标记的矩形旋转后形成的多边形
43 QPointF getSmallRotateRectCenter(QPointF ptA,QPointF ptB);//获取旋转时候矩形正上方的旋转标记矩形
44 QRectF getSmallRotateRect(QPointF ptA,QPointF ptB); 45 bool m_bRotate; 46 qreal m_RotateAngle; 47 QPointF m_RotateCenter; 48
49 private: 50 QRectF m_oldRect; 51 QPolygonF m_oldRectPolygon; 52 QRectF m_RotateAreaRect; 53 bool m_bResize; 54 QPolygonF m_insicedPolygon; 55 QRectF m_insicedRectf; 56 QPolygonF m_leftPolygon; 57 QRectF m_leftRectf; 58 QPolygonF m_topPolygon; 59 QRectF m_topRectf; 60 QPolygonF m_rightPolygon; 61 QRectF m_rightRectf; 62 QPolygonF m_bottomPolygon; 63 QRectF m_bottomRectf; 64 // QPolygonF m_rbPolygon; 65 // QRectF m_rbRectf;
66 QPointF m_startPos; 67 STATE_FLAG m_StateFlag; 68 QPointF *pPointFofSmallRotateRect; 69 protected: 70
71 }; 72 #endif // MYGRAPHICRECTITEM_H
mygraphicrectitem.cpp
1 #include "mygraphicrectitem.h"
2 #include <QtMath>
3 #include <QDebug>
4
5 myGraphicRectItem::myGraphicRectItem(QGraphicsItem *parent): 6 m_bResize(false), 7 m_oldRect(0,0,100,100), 8 m_bRotate(false), 9 m_RotateAngle(0), 10 m_StateFlag(DEFAULT_FLAG) 11 { 12 //setParent(parent);
13 setRectSize(m_oldRect); 14 setToolTip("Click and drag me!"); //提示
15 setCursor(Qt::ArrowCursor); //改变光标形状,手的形状
16 setFlag(QGraphicsItem::ItemIsMovable); 17 // setAcceptDrops(true);
18 pPointFofSmallRotateRect = new QPointF[4]; 19 SetRotate(0); 20 setFlag(QGraphicsItem::ItemIsSelectable);// 21 } 22
23 QRectF myGraphicRectItem::boundingRect() const
24 { 25 //return m_oldRectPolygon.boundingRect();
26 QRectF boundingRectF = m_oldRectPolygon.boundingRect(); 27 return QRectF(boundingRectF.x()-40,boundingRectF.y()-40,boundingRectF.width()+80,boundingRectF.height()+80); 28 } 29
30 myGraphicRectItem::~myGraphicRectItem() 31 { 32 delete []pPointFofSmallRotateRect; 33 pPointFofSmallRotateRect = nullptr; 34 } 35
36 void myGraphicRectItem::setRectSize(QRectF mrect, bool bResetRotateCenter) 37 { 38 m_oldRect = mrect; 39 if(bResetRotateCenter) 40 { 41 m_RotateCenter.setX(m_oldRect.x()+m_oldRect.width()/2); 42 m_RotateCenter.setY(m_oldRect.y()+m_oldRect.height()/2); 43 } 44 m_oldRectPolygon = getRotatePolygonFromRect(m_RotateCenter,m_oldRect,m_RotateAngle); 45
46 m_insicedRectf = QRectF(m_oldRect.x()+8,m_oldRect.y()+8,m_oldRect.width()-16,m_oldRect.height()-16); 47 m_insicedPolygon =getRotatePolygonFromRect(m_RotateCenter,m_insicedRectf,m_RotateAngle); 48
49 m_leftRectf = QRectF(m_oldRect.x(),m_oldRect.y(),8,m_oldRect.height()-8); 50 m_leftPolygon = getRotatePolygonFromRect(m_RotateCenter,m_leftRectf,m_RotateAngle); 51
52 m_topRectf = QRectF(m_oldRect.x()+8,m_oldRect.y(),m_oldRect.width()-8,8); 53 m_topPolygon = getRotatePolygonFromRect(m_RotateCenter,m_topRectf,m_RotateAngle); 54
55 m_rightRectf = QRectF(m_oldRect.right()-8,m_oldRect.y()+8,8,m_oldRect.height()-16); 56 m_rightPolygon = getRotatePolygonFromRect(m_RotateCenter,m_rightRectf,m_RotateAngle); 57
58 m_bottomRectf = QRectF(m_oldRect.x(),m_oldRect.bottom()-8,m_oldRect.width()-8,8); 59 m_bottomPolygon = getRotatePolygonFromRect(m_RotateCenter,m_bottomRectf,m_RotateAngle); 60
61 // m_rbRectf = QRectF(m_oldRect.right()-8,m_oldRect.bottom()-8,8,8); 62 // m_rbPolygon = getRotatePolygonFromRect(m_RotateCenter,m_rbRectf,m_RotateAngle);
63
64 m_SmallRotateRect = getSmallRotateRect(mrect.topLeft(),mrect.topRight());//矩形正上方的旋转标记矩形
65 m_SmallRotatePolygon = getRotatePolygonFromRect(m_RotateCenter,m_SmallRotateRect,m_RotateAngle); 66 } 67
68 void myGraphicRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 69 { 70 QPen mPen = QPen(Qt::yellow); 71 painter->setPen(mPen); 72 //绘制旋转后的矩形
73 painter->drawPolygon(m_oldRectPolygon); 74 //绘制旋转圆形
75 mPen.setWidth(2); 76 mPen.setColor(Qt::green); 77 painter->setPen(mPen); 78 QPointF pf = getSmallRotateRectCenter(m_oldRectPolygon[0],m_oldRectPolygon[1]); 79 QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20); 80 painter->drawEllipse(rect);//绘制圆形
81 painter->drawPoint(pf);//绘制点
82 } 83
84 void myGraphicRectItem::mousePressEvent(QGraphicsSceneMouseEvent *event) 85 { 86 if(event->button()== Qt::LeftButton) 87 { 88 m_startPos = event->pos();//鼠标左击时,获取当前鼠标在图片中的坐标,
89 if(m_SmallRotatePolygon.containsPoint(m_startPos,Qt::WindingFill))//旋转矩形
90 { 91 setCursor(Qt::PointingHandCursor); 92 m_StateFlag = ROTATE; 93 } 94 else if(m_insicedPolygon.containsPoint(m_startPos,Qt::WindingFill))//在矩形内框区域时按下鼠标,则可拖动图片
95 { 96 setCursor(Qt::ClosedHandCursor); //改变光标形状,手的形状
97 m_StateFlag = MOV_RECT;//标记当前为鼠标拖动图片移动状态
98 } 99 else if(m_leftPolygon.containsPoint(m_startPos,Qt::WindingFill)) 100 { 101 setCursor(Qt::SizeHorCursor); 102 m_StateFlag = MOV_LEFT_LINE;//标记当前为用户按下矩形的左边界区域
103 } 104 else if(m_rightPolygon.containsPoint(m_startPos,Qt::WindingFill)) 105 { 106 setCursor(Qt::SizeHorCursor); 107 m_StateFlag = MOV_RIGHT_LINE;//标记当前为用户按下矩形的右边界区域
108 } 109 else if(m_topPolygon.containsPoint(m_startPos,Qt::WindingFill)) 110 { 111 setCursor(Qt::SizeVerCursor); 112 m_StateFlag = MOV_TOP_LINE;//标记当前为用户按下矩形的上边界区域
113 } 114 else if(m_bottomPolygon.containsPoint(m_startPos,Qt::WindingFill)) 115 { 116 setCursor(Qt::SizeVerCursor); 117 m_StateFlag = MOV_BOTTOM_LINE;//标记当前为用户按下矩形的下边界区域
118 } 119 // else if(m_rbPolygon.containsPoint(m_startPos,Qt::WindingFill)) 120 // { 121 // setCursor(Qt::SizeFDiagCursor); 122 // m_StateFlag = MOV_RIGHTBOTTOM_RECT;//标记当前为用户按下矩形的右下角 123 // }
124 else
125 { 126 m_StateFlag = DEFAULT_FLAG; 127 } 128 } 129 else
130 { 131 QGraphicsItem::mousePressEvent(event); 132 } 133 } 134
135 void myGraphicRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 136 { 137 if(m_StateFlag == ROTATE) 138 { 139 int nRotateAngle = atan2((event->pos().x()-m_RotateCenter.x()),(event->pos().y()-m_RotateCenter.y()))*180/M_PI; 140 SetRotate(180-nRotateAngle); 141 setRectSize(m_oldRect); 142 //qDebug()<<nRotateAngle;
143 } 144 else if(m_StateFlag == MOV_RECT) 145 { 146 QPointF point = (event->pos() - m_startPos); 147 moveBy(point.x(), point.y()); 148 setRectSize(m_oldRect); 149 scene()->update(); 150 } 151 else if(m_StateFlag == MOV_LEFT_LINE) 152 { 153 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)); 154 //计算到右侧边中点的距离
155 qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y())); 156 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())); 157 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())); 158 if(dis<16||dis2LT>dis2RT) 159 { 160 return; 161 } 162 else
163 { 164 QRectF newRect(m_oldRect); 165 newRect.setLeft(m_oldRect.right()-dis); 166 newRect.setRight(m_oldRect.right()); 167 setRectSize(newRect,false); 168 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); 169 m_oldRect.moveCenter(m_RotateCenter); 170 setRectSize(m_oldRect); 171 scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
172 } 173 } 174 else if(m_StateFlag == MOV_TOP_LINE) 175 { 176 //底边中点
177 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)); 178 //计算到底边中点的距离
179 qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y())); 180 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())); 181 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())); 182 if(dis<16||dis2LT>dis2LB) 183 { 184 return; 185 } 186 else
187 { 188 QRectF newRect(m_oldRect); 189 newRect.setTop(m_oldRect.bottom()-dis); 190 newRect.setBottom(m_oldRect.bottom()); 191 setRectSize(newRect,false); 192 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); 193 m_oldRect.moveCenter(m_RotateCenter); 194 setRectSize(m_oldRect); 195 scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
196 } 197 } 198 else if(m_StateFlag == MOV_RIGHT_LINE) 199 { 200 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)); 201 //计算到左侧边中点的距离
202 qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y())); 203 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())); 204 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())); 205 if(dis<16||dis2LT<dis2RT) 206 { 207 return; 208 } 209 else
210 { 211 QRectF newRect(m_oldRect); 212 newRect.setLeft(m_oldRect.left()); 213 newRect.setRight(m_oldRect.left()+dis); 214 setRectSize(newRect,false); 215 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); 216 m_oldRect.moveCenter(m_RotateCenter); 217 setRectSize(m_oldRect); 218 scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
219 } 220 } 221 else if(m_StateFlag == MOV_BOTTOM_LINE) 222 { 223 //顶边中点
224 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)); 225 //计算到底边中点的距离
226 qreal dis = sqrt((event->pos().x()-pf.x())*(event->pos().x()-pf.x()) +(event->pos().y()-pf.y())*(event->pos().y()-pf.y())); 227 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())); 228 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())); 229 if(dis<16||dis2LT<dis2LB) 230 { 231 return; 232 } 233 else
234 { 235 QRectF newRect(m_oldRect); 236 newRect.setTop(m_oldRect.top()); 237 newRect.setBottom(m_oldRect.top()+dis); 238 setRectSize(newRect,false); 239 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); 240 m_oldRect.moveCenter(m_RotateCenter); 241 setRectSize(m_oldRect); 242 scene()->update();//必须要用scene()->update(),不能用update();否则会出现重影
243 } 244 } 245 } 246
247 void myGraphicRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) 248 { 249 setCursor(Qt::ArrowCursor); 250 if(m_StateFlag == MOV_RECT) 251 { 252 m_StateFlag = DEFAULT_FLAG; 253 } 254 else { 255 QGraphicsItem::mouseReleaseEvent(event); 256 } 257 } 258
259 void myGraphicRectItem::SetRotate(qreal RotateAngle, QPointF ptCenter) 260 { 261 m_bRotate = true; 262 if(ptCenter.x()==-999 && ptCenter.y()==-999) 263 { 264 m_RotateCenter = QPointF(m_oldRect.x()+m_oldRect.width()/2,m_oldRect.y()+m_oldRect.height()/2); 265 } 266 else
267 { 268 m_RotateCenter = ptCenter; 269 } 270 m_RotateAngle = RotateAngle; 271 this->update(); 272 } 273
274 QPointF myGraphicRectItem::getRotatePoint(QPointF ptCenter, QPointF ptIn, qreal angle) 275 { 276 double dx = ptCenter.x(); 277 double dy = ptCenter.y(); 278 double x = ptIn.x(); 279 double y = ptIn.y(); 280 double xx,yy; 281 xx = (x-dx)*cos(angle*M_PI/180)-(y-dy)*sin(angle*M_PI/180)+dx; 282 yy = (x-dx)*sin(angle*M_PI/180)+(y-dy)*cos(angle*M_PI/180)+dy; 283
284 return QPointF(xx,yy); 285 } 286
287 QList<QPointF> myGraphicRectItem::getRotatePoints(QPointF ptCenter, QList<QPointF> ptIns, qreal angle) 288 { 289 QList<QPointF> lstPt; 290 for(int i = 0;i<ptIns.count();i++) 291 { 292 lstPt.append(getRotatePoint(ptCenter,ptIns.at(i),angle)); 293 } 294 return lstPt; 295 } 296
297 QPolygonF myGraphicRectItem::getRotatePolygonFromRect(QPointF ptCenter, QRectF rectIn, qreal angle) 298 { 299 QVector<QPointF> vpt; 300 QPointF pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle); 301 vpt.append(pf); 302 pf = getRotatePoint(ptCenter,rectIn.topRight(),angle); 303 vpt.append(pf); 304 pf = getRotatePoint(ptCenter,rectIn.bottomRight(),angle); 305 vpt.append(pf); 306 pf = getRotatePoint(ptCenter,rectIn.bottomLeft(),angle); 307 vpt.append(pf); 308 pf = getRotatePoint(ptCenter,rectIn.topLeft(),angle); 309 vpt.append(pf); 310 return QPolygonF(vpt); 311 } 312
313 QRectF myGraphicRectItem::getCrtPosRectToSceen() 314 { 315 QRectF retRect = QRectF(m_oldRect.x()+pos().x(),m_oldRect.y()+pos().y(),m_oldRect.width(),m_oldRect.height()); 316 return retRect; 317 } 318 QRectF myGraphicRectItem::getSmallRotateRect(QPointF ptA,QPointF ptB) 319 { 320 QPointF pt = getSmallRotateRectCenter(ptA,ptB); 321 return QRectF(pt.x()-10,pt.y()-10,20,20); 322 } 323 QPointF myGraphicRectItem::getSmallRotateRectCenter(QPointF ptA,QPointF ptB) 324 { 325 QPointF ptCenter = QPointF((ptA.x()+ptB.x())/2,(ptA.y()+ptB.y())/2);//A,B点的中点C 326 //中垂线方程式为 y=x*k + b;
327 qreal x,y;//旋转图标矩形的中心
328 if(abs(ptB.y()-ptA.y())<0.1) 329 { 330 if(ptA.x()<ptB.x())//矩形左上角在上方
331 { 332 x = ptCenter.x(); 333 y = ptCenter.y()-20; 334 } 335 else//矩形左上角在下方
336 { 337 x = ptCenter.x(); 338 y = ptCenter.y()+20; 339 } 340 } 341 else if(ptB.y()>ptA.y())//顺时针旋转0-180
342 { 343 qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率
344 qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2; 345 //求AB线中垂线上离AB中点20个像素的点C的坐标
346 x = 20*cos(atan(k))+ptCenter.x(); 347 y = k*x+b; 348 } 349 else if(ptB.y()<ptA.y())//顺时针旋转180-360
350 { 351 qreal k = (ptA.x()-ptB.x())/(ptB.y()-ptA.y());//中垂线斜率
352 qreal b = (ptA.y()+ptB.y())/2-k*(ptA.x()+ptB.x())/2; 353 //求AB线中垂线上离AB中点20个像素的点C的坐标
354 x = -20*cos(atan(k))+ptCenter.x(); 355 y = k*x+b; 356 } 357 return QPointF(x,y); 358 }