You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QGraphicsScene.items()仅匹配pos()点而非包含点的问题排查

QGraphicsItemGroup 场景点匹配异常的原因分析

问题描述

现有一个包含多个MyItem项的QGraphicsScene,MyItem是QGraphicsItemGroup,其子项包含一个以局部原点为中心的QGraphicsEllipseItem,所有MyItem在场景中渲染正常。调用scene.items(scene_pos, selection_mode)时出现异常行为:

selection_mode行为
Qt.ContainsItemShape返回空列表
Qt.IntersectsItemShape仅当item.pos()==scene_pos时返回该项
Qt.ContainsItemBoundingRect返回空列表
Qt.IntersectsItemBoundingRect仅当item.pos()==scene_pos时返回该项

即使将scene_pos替换为其周围的小QRectF,结果仍一致。按ItemSelectionMode文档预期,IntersectsItemBoundingRect应返回相交或包含的项,但实际仅匹配pos()点——比如半径100的椭圆父项pos()为(1000,1000),scene_pos(1001,1001)本应在椭圆内,却无法匹配,仅当scene_pos为(1000,1000)时才有效。

核心原因

问题出在QGraphicsItemGroup的默认boundingRect和shape实现上:

  • QGraphicsItemGroup默认不会自动计算子项的组合边界形状,它的boundingRect()默认只返回一个包含自身原点(即pos()对应的点)的极小矩形,几乎等同于一个点。
  • 同理,它的shape()默认也只是一个包含原点的点形状,而非所有子项形状的组合。

这就导致:不管子项的椭圆范围多大,ItemGroup自身的边界和形状都只围绕它的pos()点。所以只有当查询点正好落在ItemGroup的pos()上时,才会被判定为相交或包含;其他位置哪怕在子项椭圆内部,也无法触发匹配逻辑。

解决方法

要让ItemGroup正确响应基于子项的点/区域查询,必须重写它的boundingRect()和shape()方法:

  1. 重写boundingRect():遍历所有子项,计算它们在ItemGroup坐标系下的边界,合并成一个包含所有子项的矩形。
    QRectF MyItem::boundingRect() const override {
        QRectF groupRect;
        for (QGraphicsItem *child : childItems()) {
            groupRect = groupRect.united(child->mapToParent(child->boundingRect()).boundingRect());
        }
        return groupRect;
    }
    
  2. 重写shape():合并所有子项的形状,生成ItemGroup的组合路径。
    QPainterPath MyItem::shape() const override {
        QPainterPath groupPath;
        for (QGraphicsItem *child : childItems()) {
            groupPath.addPath(child->mapToParent(child->shape()));
        }
        return groupPath;
    }
    

重写后,scene.items()就能基于子项的实际形状和边界来匹配查询点/区域,符合预期行为。

内容的提问来源于stack exchange,提问作者spraff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 17:27:42