我写了一个类,继承自QGraphicItems
然后重写了 paint(), boundingRect() 和shape() 方法
paint()绘制的图形如下图所示:
shape()中返回的是上面红线标出的区域
boundingRect() 中返回的是上面红线区域的最小外接矩形
然后我重写了mousePressEvent(),mouseMoveEvent(),mouseReleaseEvent()以实现鼠标按住上面任意一个顶点可进行图形的拉伸,如下图所示:
在这个过程中,会出现一个问题,就是鼠标拖动顶点移动几次之后,图像会接收不到鼠标点击事件,也就是再也无法拉伸上面这个图像了。
研究了半天发现,问题出在qt的QGraphicsScene场景上面:
我们在缩放QGraphicsScene内部的QGraphicItems的时候,QGraphicsScene会自动判定是否需要重新获取QGraphicItems的边框(也就是调用QGraphicItems内的boundingRect() 和shape()),换句话说,QGraphicItems内的boundingRect() 和shape()函数是否被调用,全看QGraphicsScene的心情。
而我们在缩放图形的时候,往往会把图形拉伸到超过原先的边框区域,这个时候如果QGraphicsScene不调用boundingRect() 和shape()函数的话,就会出错。
出错形式表现为:我们拉伸完item的时候,再把鼠标移上去,却触发不了item的鼠标事件
解决方法:
在拉伸的时候,也就是在mouseMoveEvent()函数内,先执行
prepareGeometryChange()
方法,通知QGraphicsScene:老子要重绘item了,你给我准备好重新获取item的边框!
然后再写根据鼠标位置重置item大小的代码,然后执行
scene()->update();//刷星界面
mousemove函数代码如下:
void mygraphicCaliperitem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
```
```
{
```
```
prepareGeometryChange();
```
```
if(m_ShapeType == CALIPER_RECT)//矩形
```
```
{
```
```
if(m_StateFlag == CALI_RECT_ROTATE)
```
```
{
```
```
qreal nRotateAngle = atan2((event->pos().x()-m_tCaliRect.m_RotateCenter.x()),(event->pos().y()-m_tCaliRect.m_RotateCenter.y()))*180/M_PI;
```
```
SetRotate(90-nRotateAngle);
```
```
//qDebug()<<nRotateAngle;
```
```
}
```
```
else if(m_StateFlag == CALI_RECT_MOVE)
```
```
{
```
```
QPointF point = (event->pos() - m_startPos);
```
```
moveBy(point.x(), point.y());
```
```
scene()->update();
```
```
}
```
```
else if(m_StateFlag == CALI_RECT_SHEAR)//控制矩形斜切
```
```
{
```
```
QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;
```
```
pc = m_tCaliRect.m_RotateCenter;
```
```
p0 = m_tCaliRect.m_RECT_Pol[0];
```
```
p1 = m_tCaliRect.m_RECT_Pol[1];
```
```
p2 = m_tCaliRect.m_RECT_Pol[2];
```
```
p3 = m_tCaliRect.m_RECT_Pol[3];
```
```
if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))
```
```
return;
```
```
//过pc做p2p3的垂线line3,line3方程为y=k3x+b3,line3与p2,p3交点为pCross3
```
```
qreal k3,b3,k4,b4;
```
```
qreal x3,y3;//pCross3(x3,y3),//y3=k3x3+b3,y3=k4x3+b4,求x3,y3
```
```
if(p3.y()==p2.y())
```
```
{
```
```
//k3不存在,lin3为x=pc.x()
```
```
//直线p2p3为y=k4x+b4
```
```
if(p3.x()==p2.x())
```
```
{
```
```
//k4不存在,直线p2p3为x=p2.x()
```
```
return;
```
```
}
```
```
else
```
```
{
```
```
k4=(p3.y()-p2.y())/(p3.x()-p2.x());
```
```
b4 = p2.y()-k4*p2.x();
```
```
//TODO:求(x3,y3)
```
```
x3 = pc.x();
```
```
y3 = k4*x3+b4;
```
```
}
```
```
}
```
```
else
```
```
{
```
```
k3 = (p2.x()-p3.x())/(p3.y()-p2.y());
```
```
b3=pc.y()-k3*pc.x();
```
```
//直线p2p3为y=k4x+b4
```
```
if(p3.x()==p2.x())
```
```
{
```
```
//k4不存在,直线p2p3为x=p2.x()
```
```
//TODO:求(x3,y3)
```
```
x3 = p2.x();
```
```
y3 = k3*x3+b3;
```
```
}
```
```
else
```
```
{
```
```
k4=(p3.y()-p2.y())/(p3.x()-p2.x());
```
```
b4 = p2.y()-k4*p2.x();
```
```
//TODO:求(x3,y3)
```
```
if(k3!=k4)
```
```
{
```
```
x3 = (b4-b3)/(k3-k4);
```
```
y3 = k3*x3+b3;
```
```
}
```
```
}
```
```
}
```
```
pCross3= QPointF(x3,y3);
```
```
```
```
//过pos做p2p3的垂线line5,line5方程为y=k5x+b5,line5与p2,p3交点为pCross5
```
```
qreal k5,b5;
```
```
qreal x5,y5;//pCross5(x5,y5),//y5=k5x5+b5,y5=k4x5+b4,求x5,y5
```
```
if(p3.y()==p2.y())
```
```
{
```
```
//k3不存在,lin5为x=event->pos().x()
```
```
//直线p2p3为y=k4x+b4
```
```
if(p3.x()==p2.x())
```
```
{
```
```
//k4不存在,直线p2p3为x=p2.x()
```
```
return;
```
```
}
```
```
else
```
```
{
```
```
k4=(p3.y()-p2.y())/(p3.x()-p2.x());
```
```
b4 = p2.y()-k4*p2.x();
```
```
//TODO:求(x5,y5)
```
```
x5 = event->pos().x();
```
```
y5 = k4*x5+b4;
```
```
}
```
```
}
```
```
else
```
```
{
```
```
k5 = (p2.x()-p3.x())/(p3.y()-p2.y());
```
```
b5=event->pos().y()-k5*event->pos().x();
```
```
//直线p2p3为y=k4x+b4
```
```
if(p3.x()==p2.x())
```
```
{
```
```
//k4不存在,直线p2p3为x=p2.x()
```
```
//TODO:求(x5,y5)
```
```
x5 = p2.x();
```
```
y5 = k5*x5+b5;
```
```
}
```
```
else
```
```
{
```
```
k4=(p3.y()-p2.y())/(p3.x()-p2.x());
```
```
b4 = p2.y()-k4*p2.x();
```
```
//TODO:求(x5,y5)
```
```
if(k5!=k4)
```
```
{
```
```
x5 = (b4-b5)/(k5-k4);
```
```
y5 = k5*x5+b5;
```
```
}
```
```
}
```
```
}
```
```
pCross5= QPointF(x5,y5);
```
```
```
```
//求pos到垂线line3的距离为disShear
```
```
double disShear = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross3.x(),pCross3.y());
```
```
double newHalfHeight;
```
```
if(m_tCaliRect.m_bKeepShadowLength)
```
```
{
```
```
if(disShear>m_tCaliRect.m_RECT.height()/2-1)
```
```
disShear = m_tCaliRect.m_RECT.height()/2-1;
```
```
newHalfHeight = sqrt(qPow(m_tCaliRect.m_RECT.height()/2,2)-disShear*disShear);
```
```
m_tCaliRect.m_fShearX = disShear/newHalfHeight;
```
```
}
```
```
else
```
```
{
```
```
m_tCaliRect.m_fShearX = disShear/(m_tCaliRect.m_RECT.height()/2);
```
```
}
```
```
//确定往左斜切还是往右斜切
```
```
if(((-90<m_tCaliRect.m_RotateAngle)&&(m_tCaliRect.m_RotateAngle<90))||(m_tCaliRect.m_RotateAngle>270 &&m_tCaliRect.m_RotateAngle<360)||m_tCaliRect.m_RotateAngle==360)
```
```
{
```
```
if(pCross5.x()<pCross3.x())
```
```
m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;
```
```
}
```
```
else if(m_tCaliRect.m_RotateAngle == 90)
```
```
{
```
```
if(pCross5.y()<pCross3.y())
```
```
m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;
```
```
}
```
```
else if(m_tCaliRect.m_RotateAngle>90&&m_tCaliRect.m_RotateAngle<270)
```
```
{
```
```
if(pCross5.x()>pCross3.x())
```
```
m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;
```
```
}
```
```
else if(m_tCaliRect.m_RotateAngle==270 ||m_tCaliRect.m_RotateAngle == -90)
```
```
{
```
```
if(pCross5.y()>pCross3.y())
```
```
m_tCaliRect.m_fShearX = -m_tCaliRect.m_fShearX;
```
```
}
```
```
if(m_tCaliRect.m_bKeepShadowLength)
```
```
{
```
```
setShearRectSize(QRectF(pc.x()-m_tCaliRect.m_RECT.width()/2,pc.y()-newHalfHeight,m_tCaliRect.m_newShearRECT.width(),newHalfHeight*2));//这个函数不会重置原始矩形的大小
```
```
}
```
```
else
```
```
{
```
```
setRectSize(m_tCaliRect.m_RECT);
```
```
}
```
```
scene()->update();
```
```
}
```
```
else if(m_StateFlag == CALI_RECT_BR)//右下角顶点
```
```
{
```
```
QPointF pc,p0,p1,p2,p3;//,pCross1,pCross2;
```
```
pc = m_tCaliRect.m_RotateCenter;
```
```
p0 = m_tCaliRect.m_RECT_Pol[0];
```
```
p1 = m_tCaliRect.m_RECT_Pol[1];
```
```
p2 = m_tCaliRect.m_RECT_Pol[2];
```
```
p3 = m_tCaliRect.m_RECT_Pol[3];
```
```
if(!get2CrossPt(p0,p1,p2,pc,event->pos(),pCross1,pCross2))
```
```
return;
```
```
// //该段代码可禁止矩形被反向拉伸!!!
```
```
// double disVertical2RightLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p1.x(),p1.y(),p2.x(),p2.y());
```
```
// double disVertical2LeftLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p3.x(),p3.y());
```
```
// if(disVertical2RightLine>disVertical2LeftLine)
```
```
// return;
```
```
// double disVertical2BottomLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p2.x(),p2.y(),p3.x(),p3.y());
```
```
// double disVertical2TopLine = CalDisPoint2longLine(event->pos().x(),event->pos().y(),p0.x(),p0.y(),p1.x(),p1.y());
```
```
// if(disVertical2BottomLine>disVertical2TopLine)
```
```
// return;
```
```
// //该段代码可禁止矩形被反向拉伸!!!
```
```
if(m_tCaliRect.m_bKeepShadowLength && m_tCaliRect.m_fShearX!=0)//保证投影长度不变
```
```
{
```
```
double disp2pc = CalDis(m_tCaliRect.m_RECTShear[2].x(),m_tCaliRect.m_RECTShear[2].y(),pc.x(),pc.y());
```
```
double dispospc = CalDis(event->pos().x(),event->pos().y(),pc.x(),pc.y());
```
```
double newHeight = dispospc/disp2pc*m_tCaliRect.m_newShearRECT.height();
```
```
double newWidth = dispospc/disp2pc*m_tCaliRect.m_newShearRECT.width();
```
```
setShearRectSize(QRectF(pc.x()-newWidth/2,pc.y()-newHeight/2,newWidth,newHeight));
```
```
double newHeightOld = dispospc/disp2pc*m_tCaliRect.m_RECT.height();
```
```
double newWidthOld = dispospc/disp2pc*m_tCaliRect.m_RECT.width();
```
```
m_tCaliRect.m_RECT = QRectF(pc.x()-newWidthOld/2,pc.y()-newHeightOld/2,newWidthOld,newHeightOld);
```
```
}
```
```
else//投影长度可变
```
```
{
```
```
//新矩形宽度一半:
```
```
double dispcpCross1 = CalDis(pc.x(),pc.y(),pCross1.x(),pCross1.y());
```
```
if(dispcpCross1<10)
```
```
return;//矩形宽度不能小于20
```
```
//新矩形高度一半:
```
```
double disVertical = CalDisPoint2longLine(event->pos().x(),event->pos().y(),pc.x(),pc.y(),pCross1.x(),pCross1.y());
```
```
if(disVertical<10)
```
```
return;//矩形高度不能小于20
```
```
setRectSize(QRectF(pc.x()-dispcpCross1,pc.y()-disVertical,dispcpCross1*2,disVertical*2));
```
```
```
```
}
```
```
scene()->update();
```
```
}
```
```
}
}