QGraphicsItem.itemClipsChildrenToShape PySide2 中的问题

QGraphicsItem.itemClipsChildrenToShape issue in PySide2

我正在尝试结合使用 PySide2 和 PyQtGraph 创建 Smith 圆图 canvas。 按照上一个问题 (Pyqtgraph clip line) 中的描述,这样做的最佳方法似乎是使用 QGraphicsEllipseItem 绘制外圆,使用 QGraphicsPathItem 和 [=14 绘制所有内弧=],然后将它们添加到外圈并使用 ItemClipsChildrenToParent.

剪辑它们

这是我的代码:

rline = [0.2, 0.5, 1.0, 2.0, 5.0]
xline = [0.2, 0.5, 1, 2, 5]

circle1 = QGraphicsEllipseItem(-1, -1, 2, 2)
circle1.setPen(mkPen('b', width=0.5))
circle1.setFlag(circle1.ItemClipsChildrenToShape)

pathItem = QGraphicsPathItem()
path = QPainterPath()
path.moveTo(1, 0)

for r in rline:
    raggio = 1./(1+r)
    path.addEllipse(1, -raggio, -raggio*2, raggio*2)

for x in xline:
    path.arcTo(1-x, 0, x*2, x*2, 90, 180)
    path.moveTo(1, 0)
    path.arcTo(1-x, 0, x*2, -x*2, 90, 180)

pathItem.setPath(path)
pathItem.setPen(mkPen('b', width = 0.5))
pathItem.setParentItem(circle1)

我的代码似乎大部分都在工作,如下图所示。

问题是内弧并没有完全被外圆包围。我原以为剪裁应该是绝对的,这样 children 就不能绘制在 parents 边界之外,但也许情况并非如此?

pyqtGraph 默认创建 cosmetic 笔,这些笔的宽度始终基于它们绘制的设备:如果您指定宽度等于的装饰笔0.5,它将始终具有该大小,无论用于视图的比例如何。

现在,问题的根源可以在关于 QGraphicsItem.shape() 的文档中找到,其中指定:

The outline of a shape can vary depending on the width and style of the pen used when drawing.

Qt 无法知道化妆笔的实际范围(因为它完全取决于绘画设备,并且同一场景可以有 多个 视图,每个视图都有自己的变换. 结果是它根据指定的笔宽计算 shapeeven 如果它是化妆品。

由于您使用的值非常小,0.5 的笔宽实际上会变得 非常大,并且形状的范围会因该尺寸而大大增加,这就是它的原因似乎 children 不符合形状:如果你有一个 2x2 的椭圆,使用 0.5 的笔,得到的形状将是一个 2.5x2.5 的椭圆(因为笔的范围是其宽度的一半)。

解决方案是完全忽略 shape() 的默认行为,只使用子类 return 椭圆的形状:

class Ellipse(QGraphicsEllipseItem):
    def shape(self):
        path = QPainterPath()
        path.addEllipse(self.rect())
        return path

circle1 = Ellipse(-1, -1, 2, 2)
# ...