自定义边界矩形的形状

时间:2014-10-09 06:21:48

标签: qt bounding-box qgraphicsitem

我正在使用鼠标点击绘制一条线。使用paint函数绘制线条:

painter->drawLine(start_p, end_p);

行的边界矩形定义为:

QRectF Line::boundingRect() const
{
  // bounding rectangle for line
  return QRectF(start_p, end_p).normalized();
}

enter image description here

这表示画线。我得到了这个的边界矩形,如下所示:

enter image description here

我想根据项目的形状设置边界矩形,例如:enter image description here

如何实现这一目标?

修改

在选择任何重叠线条时,选择顶部带有边界矩形的线条(参见下图)。即使使用setZValue也不会在这里工作。 我想通过最小化线条形状的边界矩形来实现这一点。

enter image description here

4 个答案:

答案 0 :(得分:7)

如果您的项目形状不是矩形,或者是旋转的矩形,请使用QGraphicsItem::shape

此函数应返回QPainterPath。您应该可以使用QPainterPath::addPolygon创建路径。

这是一个小例子:

QPainterPath Item::shape() const
{
    QPainterPath path;
    QPolygon polygon;
    polygon << QPoint(0, 0);
    polygon << QPoint(5, 5);
    polygon << QPoint(width, height);
    polygon << QPoint(width - 5, height - 5);
    path.addPolygon(polygon);

    return path;
}

你当然应该以不同的方式计算你在路径中的积分,但是你明白了。现在,当您点击某个项目时,只有在QPainterPath定义的形状内发生了点击时,它才会选择它。

如果您需要制作曲线,可以按照cmannett85的建议使用QPainterPathStroker::createStroke

答案 1 :(得分:1)

QGraphicsItem中有两个您应该感兴趣的相关函数。第一个是boundingRect。您可能已经意识到这是一个包含整个项目的矩形。 Qt使用它来快速计算项目的可见程度和简单的项目碰撞等。

如果你有长方形物品那就太棒了;您可以在从QGraphicsItem或QGraphicsObject继承的任何项目中覆盖boundingRect()

如果你的形状不规则并且你想要做一些事情,比如碰撞一个项目的形状,那么shape()函数也需要覆盖你的班级。

这将返回一个QPainterPath,因此您可以执行以下操作: -

QPainterPath Line::shape()
{
    QRectF rect(start_p, end_p).normalized();

    // increase the rect beyond the width of the line
    rect.adjust(-2, -2, 2, 2); 

    QPainterPath path;
    path.addRect(rect);

    return path;    // return the item's defined shape
}

现在,您可以使用画家绘制shape()项,而不是boundingRect(),并且碰撞将按预期工作。

答案 2 :(得分:1)

boundingRect总是用于优化场景的绘画过程。所以你在这里没有操纵的余地。

但是如果您想要更改鼠标互动区域,则shape method。默认情况下,此方法返回从QPainterPath方法收到的boundingRect矩形 因此,只需覆盖此方法并提供所需的形状。

QPainterPath YourGraphicsItem::shape() const {
     static const qreal kClickTolerance = 10;

     QPointF vec = end_p-start_p;
     vec = vec*(kClickTolerance/qSqrt(QPointF::dotProduct(vec, vec)));
     QPointF orthogonal(vec.y(), -vec.x());

     QPainterPath result(start_p-vec+orthogonal);
     result.lineTo(start_p-vec-orthogonal);
     result.lineTo(end_p+vec-orthogonal);
     result.lineTo(end_p+vec+orthogonal);
     result.closeSubpath();

     return result;
}

答案 3 :(得分:-1)

如果你想要这样的东西,你必须画出自己的界限。让Qt让它的QRect进行边界定义,并定义你的新QRect依赖于前一个QRect的角落,左上角和右下角。例如,如果左上角是(2,2),你的新QRect左上角是(1,2),右上角是(2,1)......(