PySide2 中的 QGraphicsItem.itemClipsChildrenToShape 问题
Posted
技术标签:
【中文标题】PySide2 中的 QGraphicsItem.itemClipsChildrenToShape 问题【英文标题】:QGraphicsItem.itemClipsChildrenToShape issue in PySide2 【发布时间】:2021-11-16 21:56:54 【问题描述】:我正在尝试使用 PySide2 和 PyQtGraph 的组合创建史密斯圆图画布。
如上一个问题 (Pyqtgraph clip line) 中所述,执行此操作的最佳方法似乎是使用QGraphicsEllipseItem
绘制外圆,使用QGraphicsPathItem
和QPainterPath
绘制所有内弧,然后将它们添加到外圈并使用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)
如下图所示,我的代码似乎大部分都在工作。
问题是内圆弧并没有完全被外圆约束。我原以为剪裁应该是绝对的,这样孩子们就不能在父母的界限之外画画,但也许不是这样?
【问题讨论】:
【参考方案1】:pyqtGraph 默认创建 cosmetic 笔,这些笔的宽度始终基于它们绘制的设备:如果您指定宽度等于 0.5 的化妆笔,它将 总是不管视图使用的比例是多少。
现在,问题的根源可以在有关QGraphicsItem.shape()
的文档中找到,其中指定:
形状的轮廓可能会因绘图时使用的笔的宽度和样式而异。
Qt 无法知道化妆笔的实际范围(因为它完全依赖于绘图设备,并且同一个场景可以有多个视图,每个视图都有自己的变换。结果是它根据指定的笔宽计算 shape,如果是装饰性的 even。
由于您使用的值非常小,因此 0.5 笔宽度实际上变得非常大,并且形状的范围大大增加了该尺寸,这就是为什么看起来孩子们不考虑形状:如果您有一个 2x2 的椭圆,使用 0.5 的笔,生成的形状将是一个 2.5x2.5 的椭圆(因为笔的范围是其宽度的一半)。
解决办法是完全忽略shape()
的默认行为,只使用子类返回椭圆的形状:
class Ellipse(QGraphicsEllipseItem):
def shape(self):
path = QPainterPath()
path.addEllipse(self.rect())
return path
circle1 = Ellipse(-1, -1, 2, 2)
# ...
【讨论】:
以上是关于PySide2 中的 QGraphicsItem.itemClipsChildrenToShape 问题的主要内容,如果未能解决你的问题,请参考以下文章
Qt 获取QGraphicsItem在屏幕上的位置,在QGraphicsItem中获取全局位置,转换为screenPos
从 QGraphicsItem 上的上下文菜单操作中获取事件
PySide/PyQT5:如何从 QGraphicsItem 发出信号?