效果如下:
我通过重写一个继承自QGraphicitem的类来实现上述功能,绘制重叠区域主要通过QPainterPath来实现,核心代码如下:
void myGraphicRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPen mPen= QPen(Qt::yellow);
painter->setPen(mPen);
//绘制旋转后的矩形
painter->drawPolygon(m_oldRectPolygon);
//绘制旋转圆形
mPen.setWidth(2);
mPen.setColor(Qt::green);
painter->setPen(mPen);
QPointF pf = getSmallRotateRectCenter(m_oldRectPolygon[0],m_oldRectPolygon[1]);
QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);
painter->drawEllipse(rect);//绘制圆形
painter->drawPoint(pf);//绘制点
//有重叠的情况
if(!this->scene()->collidingItems(this).isEmpty())
{
QPainterPath path,pathOthers;
QList<QGraphicsItem *> lstcolliItems = this->scene()->collidingItems(this);
int nColliNum = lstcolliItems.count();
for(int i = 0;i<nColliNum;i++)
{
QGraphicsItem* pTempItem = this->scene()->collidingItems(this)[i];
QPainterPath tempPath = pTempItem->shape();
tempPath.translate(pTempItem->pos());//转换到view中的坐标
pathOthers += tempPath;//记录与本item重叠的item的路径
}
path.addPolygon(m_oldRectPolygon);
path.translate(this->pos());//转换到view中的坐标
path &= pathOthers;//计算重叠部分的路径path
path.translate(-this->pos().x(),-this->pos().y());//转换回本Item中的坐标
QBrush brush(Qt::cyan);
mPen.setColor(Qt::blue);
painter->setPen(mPen);
painter->setBrush(brush);
painter->drawPath(path);//绘制重叠区域
}
}
我写的类的paint函数完整代码如下:
`void mygraphicCaliperitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPen mPen;
mPen= QPen(Qt::yellow);
painter->setPen(mPen);
if(m_ShapeType == CALIPER_RECT)//
{
//设置笔刷为图片平铺
QImage image(":/maskP");
QBrush brush(image);
brush.setStyle(Qt::TexturePattern);//设置平铺模式
painter->setBrush(brush);
//绘制旋转后的矩形
if(m_bSelected)
painter->setPen(QPen(Qt::green,2));
else
painter->setPen(QPen(Qt::green,1));
painter->drawPolygon(m_tCaliRect.m_RECT_Pol);
mPen.setColor(Qt::yellow);
//绘制右下角顶点矩形
mPen.setWidth(1);
painter->setPen(mPen);
//绘制右下角顶点矩形
QPainterPath path;
path.moveTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[0].x()+m_tCaliRect.m_RECT_BR_Pol[1].x())/2,(m_tCaliRect.m_RECT_BR_Pol[0].y()+m_tCaliRect.m_RECT_BR_Pol[1].y())/2));
path.lineTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[2].x()+m_tCaliRect.m_RECT_BR_Pol[3].x())/2,(m_tCaliRect.m_RECT_BR_Pol[2].y()+m_tCaliRect.m_RECT_BR_Pol[3].y())/2));
path.moveTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[0].x()+m_tCaliRect.m_RECT_BR_Pol[3].x())/2,(m_tCaliRect.m_RECT_BR_Pol[0].y()+m_tCaliRect.m_RECT_BR_Pol[3].y())/2));
path.lineTo(QPointF((m_tCaliRect.m_RECT_BR_Pol[2].x()+m_tCaliRect.m_RECT_BR_Pol[1].x())/2,(m_tCaliRect.m_RECT_BR_Pol[2].y()+m_tCaliRect.m_RECT_BR_Pol[1].y())/2));
painter->setPen(QPen(Qt::yellow,2));
painter->drawPath(path);
//绘制投影标记
QPointF pt0 = m_tCaliRect.m_RECT_Shadow_Dir_Pol[0];
QPointF pt1 = QPointF((m_tCaliRect.m_RECT_Shadow_Dir_Pol[2].x()+m_tCaliRect.m_RECT_Shadow_Dir_Pol[3].x())/2,(m_tCaliRect.m_RECT_Shadow_Dir_Pol[2].y()+m_tCaliRect.m_RECT_Shadow_Dir_Pol[3].y())/2);
QPointF pt2 = m_tCaliRect.m_RECT_Shadow_Dir_Pol[1];
painter->drawLine(pt0,pt1);
painter->drawLine(pt2,pt1);
//绘制扫描方向标记
painter->drawPolygon(m_tCaliRect.m_RECT_Scan_Dir_Pol);
//绘制旋转圆形
mPen.setWidth(2);
painter->setPen(mPen);
QPointF pf = QPointF((m_tCaliRect.m_RECT_Pol[1].x()+m_tCaliRect.m_RECT_Pol[2].x())/2,(m_tCaliRect.m_RECT_Pol[1].y()+m_tCaliRect.m_RECT_Pol[2].y())/2);
QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);
painter->drawEllipse(rect);//绘制圆形
painter->drawPoint(pf);//绘制点
//绘制切变矩形标记
painter->drawPolygon(m_tCaliRect.m_RECT_Shear_Pol);
//painter->drawPolygon(m_RECT_Inside_Pol);
// mPen.setColor(Qt::red); // mPen.setWidth(5); // painter->setPen(mPen); // painter->drawPoint(pCross1); // painter->drawPoint(pCross2); // painter->drawPoint(pCross3); // painter->drawPoint(m_RECT.center()); } else if(m_ShapeType == CALIPER_LINE)//直线卡尺 { mPen.setColor(Qt::yellow); mPen.setWidth(2); painter->drawLine(m_CaliLine);
mPen.setWidth(1);
int nCount = m_tCaliRectLst.count();
for(int i = 0;i<nCount;i++)
{
//painter->setPen(QPen(Qt::green,1));
//绘制旋转后的矩形
if(m_bSelected)
painter->setPen(QPen(Qt::green,2));
else
painter->setPen(QPen(Qt::green,1));
painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Pol);
if((nCount+1)/2-1==i)
{
//绘制右下角顶点矩形
QPainterPath path;
path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));
path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));
path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));
path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));
painter->setPen(QPen(Qt::yellow,2));
painter->drawPath(path);
//绘制投影标记
painter->setPen(QPen(Qt::yellow,1));
QPointF pt0 = m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[0];
QPointF pt1 = QPointF((m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[2].x()+m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[2].y()+m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[3].y())/2);
QPointF pt2 = m_tCaliRectLst[i].m_RECT_Shadow_Dir_Pol[1];
painter->drawLine(pt0,pt1);
painter->drawLine(pt2,pt1);
//绘制扫描方向标记
painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Scan_Dir_Pol);
#ifdef ROTATE_AND_SHEAR //绘制旋转圆形 painter->setPen(QPen(Qt::yellow,2)); QPointF pf = QPointF((m_tCaliRectLst[i].m_RECT_Pol[1].x()+m_tCaliRectLst[i].m_RECT_Pol[2].x())/2,(m_tCaliRectLst[i].m_RECT_Pol[1].y()+m_tCaliRectLst[i].m_RECT_Pol[2].y())/2); QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20); painter->drawEllipse(rect);//绘制圆形 painter->drawPoint(pf);//绘制点 //绘制切变矩形标记 painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Shear_Pol); #endif } } mPen= QPen(Qt::red); mPen.setWidth(4); painter->setPen(mPen); painter->drawPoint(m_CaliLine.p1()); painter->drawPoint(m_CaliLine.p2()); // painter->drawPolygon(m_LineBodyPol);//直线上下各10像素范围内的矩形区域 // painter->drawEllipse(m_LineP1); // painter->drawEllipse(m_LineP2); } else if(m_ShapeType == CALIPER_CIRCLE)//圆形卡尺 { int nCount = m_tCaliRectLst.count(); for(int i = 0;i<nCount;i++) { //绘制旋转后的矩形 if(m_bSelected) painter->setPen(QPen(Qt::green,2)); else painter->setPen(QPen(Qt::green,1)); painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Pol);
//绘制右下角顶点矩形十字
if((nCount+1)/2-1==i)
{
QPainterPath path;
path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));
path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));
path.moveTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[0].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[0].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[3].y())/2));
path.lineTo(QPointF((m_tCaliRectLst[i].m_RECT_BR_Pol[2].x()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].x())/2,(m_tCaliRectLst[i].m_RECT_BR_Pol[2].y()+m_tCaliRectLst[i].m_RECT_BR_Pol[1].y())/2));
painter->setPen(QPen(Qt::yellow,2));
painter->drawPath(path);
//绘制扫描方向标记
painter->setPen(QPen(Qt::yellow,1));
painter->drawPolygon(m_tCaliRectLst[i].m_RECT_Scan_Dir_Pol);
}
}
//painter->drawEllipse(QRectF(m_CircleCenter.x()-m_radius,m_CircleCenter.y()-m_radius,m_radius*2,m_radius*2));
painter->setPen(QPen(Qt::red,4));
painter->drawPoint(m_CircleP1);
painter->drawPoint(m_CircleP2);
painter->drawPoint(m_CircleP3);
qreal angle1 = atan2(m_CircleP1.x()-m_CircleCenter.x(),m_CircleP1.y()-m_CircleCenter.y())*180/M_PI-90;
//qDebug()<<"angle1:"<<angle1<<endl;
if(angle1<0)
angle1 = 360+angle1;
if(angle1>360)
angle1 = angle1-360;
qreal angle3 = atan2(m_CircleP3.x()-m_CircleCenter.x(),m_CircleP3.y()-m_CircleCenter.y())*180/M_PI-90;
//qDebug()<<"angle3:"<<angle3<<endl;
if(angle3<0)
angle3 = 360+angle3;
if(angle3>360)
angle3 = angle3-360;
qreal angle0 = angle3-angle1;
if(angle0<0)
angle0 = 360+angle0;
if(angle0>360)
angle0 = angle0-360;
painter->setPen(QPen(Qt::yellow,1));
qreal s= (m_CircleP1.x() - m_CircleP3.x()) * (m_CircleP2.y() - m_CircleP3.y()) - (m_CircleP2.x() - m_CircleP3.x())*(m_CircleP1.y() - m_CircleP3.y());//向量p3p1和p3p2的叉积
if(s>0)//叉积方向决定了弧形是内弧还是外弧
{
painter->drawArc(m_CircleRect,(int)angle3*16,(int)(360-angle0)*16);
}
else
{
painter->drawArc(m_CircleRect,(int)angle1*16,(int)angle0*16);
}
//qDebug()<<"angle1:"<<angle1<<"angle3:"<<angle3<<"angle0:"<<angle0<<"s:"<<s;
//绘制补全圆使用的双向箭头
QPainterPath path = getFillCircleArrow(m_CircleP1,m_CircleCenter,m_radius,10);
painter->setPen(QPen(Qt::green,1));
painter->drawPath(path);
path = getFillCircleArrow(m_CircleP3,m_CircleCenter,m_radius,10);
painter->drawPath(path);
}
else if(m_ShapeType == C_CIRCLE)//圆形
{
if(m_bSelected)
painter->setPen(QPen(Qt::green,2));
else
painter->setPen(QPen(Qt::green,1));
painter->drawEllipse(m_tCircle.m_RECT);
//绘制缩放用的x标记
QPainterPath path;
path.moveTo(QPointF((m_tCircle.m_RECT_BR_Pol[0].x()+m_tCircle.m_RECT_BR_Pol[1].x())/2,(m_tCircle.m_RECT_BR_Pol[0].y()+m_tCircle.m_RECT_BR_Pol[1].y())/2));
path.lineTo(QPointF((m_tCircle.m_RECT_BR_Pol[2].x()+m_tCircle.m_RECT_BR_Pol[3].x())/2,(m_tCircle.m_RECT_BR_Pol[2].y()+m_tCircle.m_RECT_BR_Pol[3].y())/2));
path.moveTo(QPointF((m_tCircle.m_RECT_BR_Pol[0].x()+m_tCircle.m_RECT_BR_Pol[3].x())/2,(m_tCircle.m_RECT_BR_Pol[0].y()+m_tCircle.m_RECT_BR_Pol[3].y())/2));
path.lineTo(QPointF((m_tCircle.m_RECT_BR_Pol[2].x()+m_tCircle.m_RECT_BR_Pol[1].x())/2,(m_tCircle.m_RECT_BR_Pol[2].y()+m_tCircle.m_RECT_BR_Pol[1].y())/2));
painter->setPen(QPen(Qt::yellow,2));
painter->drawPath(path);
}
else if(m_ShapeType == C_ELLIPSE)//椭圆
{
if(m_bSelected)
painter->setPen(QPen(Qt::green,2));
else
painter->setPen(QPen(Qt::green,1));
//绘制旋转后的圆形
QTransform trans0;
QPainterPath path0;
trans0.translate(m_tEllipse.m_RotateCenter.x(),m_tEllipse.m_RotateCenter.y());
trans0.rotate(m_tEllipse.m_RotateAngle,Qt::ZAxis);
trans0.translate(-m_tEllipse.m_RotateCenter.x(),-m_tEllipse.m_RotateCenter.y());
path0.addEllipse(m_tEllipse.m_RECT);
path0 = trans0.map(path0);//将pathTemp旋转m_RotateAngle角度
painter->drawPath(path0);//drawPolygon(m_RECT_Pol);
//绘制旋转圆形标记
mPen.setWidth(2);
mPen.setColor(Qt::green);
painter->setPen(mPen);
QPointF pf = getVeritacalLinePoint(m_tEllipse.m_RECT_Pol[0],m_tEllipse.m_RECT_Pol[1]);
QRectF rect = QRectF(pf.x()-10,pf.y()-10,20,20);
painter->drawEllipse(rect);//绘制圆形
painter->drawPoint(pf);//绘制点
//绘制双向箭头
painter->setPen(QPen(Qt::green,1));
painter->drawPath(getScaleEllipseArror(m_tEllipse.m_RECT_Pol));
}
else if(m_ShapeType == C_LINE)
{
//绘制旋转后的矩形
if(m_bSelected)
painter->setPen(QPen(Qt::green,2));
else
painter->setPen(QPen(Qt::green,1));
QPainterPath path0;
path0.moveTo(m_Line.p1());
path0.lineTo(m_Line.p2());
painter->drawPath(path0);
//绘制直线的两端点标记
painter->setPen(QPen(Qt::red,4));
painter->drawPoint(m_Line.p1());
painter->drawPoint(m_Line.p2());
}
else if(m_ShapeType == C_MASK)
{
QRect nRect(0,0,2000, 2000);
QPixmap littleImage;
littleImage = m_BlackWhiteBigImg.copy(nRect);
QPixmap pix = pixmapToPath(littleImage);
painter->setOpacity(0.2);
painter->drawPixmap(nRect,pix);
// qDebug()<<"option->rect:"<rect; // qDebug()<<"m_Line:"<<m_Line.p1()<<m_Line.p2(); } else if(m_ShapeType == C_POLYGON) { //绘制多边形 if(m_bSelected) painter->setPen(QPen(Qt::green,2)); else painter->setPen(QPen(Qt::green,1)); painter->drawPolygon(m_oldPolygon); //绘制每个点 painter->setPen(QPen(Qt::red,4)); for(int i = 0;i<m_oldPolygon.size();i++) { painter->drawPoint(m_oldPolygon[i]); } }
//有重叠的情况
if(!this->scene()->collidingItems(this).isEmpty())
{
QPainterPath path,pathOthers;
QList<QGraphicsItem *> lstcolliItems = this->scene()->collidingItems(this);
int nColliNum = lstcolliItems.count();
for(int i = 0;i<nColliNum;i++)
{
if(lstcolliItems[i]->type()==UserType+1)
{
mygraphicCaliperitem* pTempItem = (mygraphicCaliperitem*)lstcolliItems[i];
if(pTempItem->zValue()==0)
{
QPainterPath tempPath = pTempItem->getCollideShape();
tempPath.translate(pTempItem->pos());//转换到view中的坐标
pathOthers += tempPath;//记录与本item重叠的item的路径
}
}
}
path=getCollideShape();
path.translate(this->pos());//转换到view中的坐标
path &= pathOthers;//计算重叠部分的路径path
path.translate(-this->pos().x(),-this->pos().y());//转换回本Item中的坐标
//QBrush brush(Qt::cyan);
//设置笔刷为图片平铺
QImage image(":/maskP");
QBrush brush(image);
brush.setStyle(Qt::TexturePattern);//设置平铺模式
mPen.setColor(Qt::blue);
painter->setPen(mPen);
painter->setBrush(brush);
painter->drawPath(path);//绘制重叠区域
}
}`