本例程通过重写了一个类,继承自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 }