自定义边界矩形的形状
Posted
技术标签:
【中文标题】自定义边界矩形的形状【英文标题】:Customizing shape of bounding rect 【发布时间】:2014-10-09 06:21:48 【问题描述】:我正在使用鼠标点击画一条线。使用paint函数绘制线条为:
painter->drawLine(start_p, end_p);
线的边界矩形定义为:
QRectF Line::boundingRect() const
// bounding rectangle for line
return QRectF(start_p, end_p).normalized();
这显示了绘制的线条。我得到了如图所示的边界矩形:
我想根据项目的形状设置边界矩形,例如:
如何做到这一点?
编辑
在选择任何重叠线时,会选择顶部有边界矩形的那条(见下图)。即使使用setZValue
在这里也行不通。
我想通过将边界矩形最小化为线的形状来实现这一点。
【问题讨论】:
这是一个交叉帖子。 :) 使用QGraphicsItem::shape
。
我是新手。能否请您提供一些演示代码。
您检查了我链接的文档吗?那里有一个例子。还要检查QPainterPath
的文档。您也许可以使用QPainterPath::addPolygon
创建您的形状。
您无法更改边界框的形状或方向。但是您可以更改用于碰撞和撞击测试的形状(如@thuga 所示)- 您的意思是这样吗?
【参考方案1】:
如果您的项目不是矩形或旋转矩形,请使用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
。
【讨论】:
【参考方案2】:您应该对 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(),并且碰撞将按预期工作。
【讨论】:
【参考方案3】:boundingRect
一直用于优化场景的绘制过程。所以这里没有任何操纵的余地。
但是如果你想改变鼠标交互的区域,有shape
method。默认情况下,此方法返回从boundingRect
方法接收到的QPainterPath
矩形。
所以只需覆盖此方法并提供所需的形状。
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;
【讨论】:
【参考方案4】:如果你想要这样的东西,你必须画出自己的边界。让 Qt 将其 QRect 用于边界并定义新的 QRect 依赖于先前 QRect 的角,左上角和右下角。例如,如果左上角是 (2,2) 你的新 QRect 左上角是 (1,2) 而右上角是 (2,1) 和 ....
【讨论】:
“如果你想要这样的东西,你必须画出自己的边界”这根本不是真的。 简化我的观点并说(这根本不是真的)很简单。如果你能回答这个问题。我通过 QGraphicsView 创建了一个具有所有这些功能的整个项目。如果你没有看到这个东西你不能说它不是真的。 我可以回答这个问题,但@thuga 已在 45 分钟前的评论中提供了答案,并且代表是他/她的要求。您的答案是错误的,因为您不需要按顺序绘制边界来设置它们,您可以覆盖QGraphicsItem::boundingRect()
。此外,边界框是轴对齐的,因此绘制一个旋转的矩形会导致实际的边界框更大。以上是关于自定义边界矩形的形状的主要内容,如果未能解决你的问题,请参考以下文章