QGraphicsItem中的碰撞检测描述

 

QGraphicsItem中的碰撞检测描述

    QGraphicsItem是图元基类。QGraphics View框架提供了几种标准的图元,如矩形(QGraphicsRectItem、椭圆(QGraphicsEllipseItem)和文本图元(QGraphicsTextItem)等。用户可以继承QgraphicItem实现符合自己需要的图元。

QGraphicsItem具有以下功能:

  • 处理鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件

  • 处理键盘输入事件

  • 处理拖放事件

  • 分组

  • 碰撞检测

  图元有自己的坐标系统,也提供场景和图元、图元与图元之间的坐标转换函数。图元可以包含子图元。

 

    要创建自己的图元,必须首先创建QGrahicsItem的一个子类,然后开始实现他的2个纯虚函数。一个是boundingRect(),用于返回图元绘制所需要的估测区域。另一个是paint,它实现实际的绘图操纵。举例:

class SimpleItem : public QGraphicsItem
{
public:

QRectF boundingRect() const
{

qreal penWidth = 1;
return QRectF(-10 - penWidth / 2, -10 - penWidth / 2,
20 + penWidth / 2, 20 + penWidth / 2);

}

void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{

painter->drawRoundedRect(-10, -10, 20, 20, 5, 5);

}

};

    boundingRect函数有几个目的。QGraphicsScene的图元索引就是建立在boundingRect的基础上。QGraphicsView也使用这个函数来从视图上将不可见的图元移去,以及在绘制重叠的图元时决定需要重新组织的区域。另外,QGraphicsItem的碰撞检测机制(collision detection)使用boundingRest来提高高效的处理。更好的碰撞检测算法是基于shape函数的调用,shape函数将图元的形状的准确外观以QPainterPath返回。

    QGraphicsScene认为所有图元的boundingRect函数与shape函数都是不发生改变的,除非用户进行通知。如果你想改变一个图元的范围,必需先调用prepareGeometryChange以允许QGraphicsScene进行更新。

碰撞检测可以通过以下两种方式实现:

  • 重新实现shape函数返回一个准确的图元外观形状,依赖collidesWithItem函数进行缺省的碰撞检测,如果形状非常的复杂,该检测将是非常耗时的。
  • 重新实现collidesWithItem函数,为自己的定制图元编写碰撞检测算法。

 

对于多点成线的图元可以使用下面的方式返回shape。

QPainterPath path;
//直线的绘制路径
if (m_pointList.count()>0)
{

int iSize;
iSize = m_pointList.size();
path.moveTo (m_pointList[0]);

for(int i=1;i<iSize/2;i++)
{
    path.lineTo (m_pointList[i*2]);
}
for(int i=iSize/2;i>=1;i--)
{
    path.lineTo (m_pointList[i*2-1]);
}
path.closeSubpath();

}
return path;

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QGraphicsItem碰撞检测失效,可能是因为你没有正确地实现碰撞检测函数。 在自定义 QGraphicsItem ,你需要实现 `shape()` 函数来指定该 item 的形状,这个形状用于在碰撞检测计算碰撞。如果你没有正确地实现 `shape()` 函数,那么在碰撞检测就会出现问题。 具体来说,你需要在 `shape()` 函数返回一个 `QPainterPath` 对象,该对象描述了该 item 的形状。这个形状应该是一个不包含任何透明部分的完整形状。 例如,如果你的自定义 QGraphicsItem 是一个圆形,那么可以这样实现 `shape()` 函数: ```cpp QPainterPath MyItem::shape() const { QPainterPath path; path.addEllipse(boundingRect()); // 添加一个椭圆形状 return path; } ``` 如果你的自定义 QGraphicsItem 是一个矩形,那么可以这样实现 `shape()` 函数: ```cpp QPainterPath MyItem::shape() const { QPainterPath path; path.addRect(boundingRect()); // 添加一个矩形形状 return path; } ``` 如果你的自定义 QGraphicsItem 是一个复杂形状,那么你需要使用更多的 QPainterPath 函数来构建这个形状。 实现 `shape()` 函数后,你可以使用 `collidesWithItem()` 函数来检测两个 item 是否发生了碰撞。例如: ```cpp bool MyItem::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelectionMode mode) const { return shape().intersects(other->shape()); } ``` 这个函数会在两个 item 的形状相交时返回 true,否则返回 false。 如果你仍然无法解决问题,请提供更多的代码和详细的描述,以便更好地帮助你解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值