Source code for pyqtgraph.graphicsItems.FillBetweenItem
from typing import Union
from .. import functions as fn
from ..Qt import QtGui, QtWidgets, QtCore
from .PlotCurveItem import PlotCurveItem
from .PlotDataItem import PlotDataItem
__all__ = ['FillBetweenItem']
[docs]
class FillBetweenItem(QtWidgets.QGraphicsPathItem):
"""
GraphicsItem filling the space between two PlotDataItems.
"""
[docs]
def __init__(
self,
curve1: Union[PlotDataItem, PlotCurveItem],
curve2: Union[PlotDataItem, PlotCurveItem],
brush=None,
pen=None,
fillRule: QtCore.Qt.FillRule=QtCore.Qt.FillRule.OddEvenFill
):
"""FillBetweenItem fills a region between two curves with a specified
:class:`~QtGui.QBrush`.
Parameters
----------
curve1 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
Line to draw fill from
curve2 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
Line to draw fill to
brush : color_like, optional
Arguments accepted by :func:`~pyqtgraph.mkBrush`, used
to create the :class:`~QtGui.QBrush` instance used to draw the item
by default None
pen : color_like, optional
Arguments accepted by :func:`~pyqtgraph.mkColor`, used
to create the :class:`~QtGui.QPen` instance used to draw the item
by default ``None``
fillRule : QtCore.Qt.FillRule, optional
FillRule to be applied to the underlying :class:`~QtGui.QPainterPath`
instance, by default ``QtCore.Qt.FillRule.OddEvenFill``
Raises
------
ValueError
Raised when ``None`` is passed in as either ``curve1``
or ``curve2``
TypeError
Raised when either ``curve1`` or ``curve2`` is not either
:class:`~pyqtgraph.PlotDataItem` or :class:`~pyqtgraph.PlotCurveItem`
"""
super().__init__()
self.curves = None
self._fillRule = fillRule
if curve1 is not None and curve2 is not None:
self.setCurves(curve1, curve2)
elif curve1 is not None or curve2 is not None:
raise ValueError("Must specify two curves to fill between.")
if brush is not None:
self.setBrush(brush)
self.setPen(pen)
self.updatePath()
def fillRule(self):
return self._fillRule
[docs]
def setFillRule(self, fillRule: QtCore.Qt.FillRule=QtCore.Qt.FillRule.OddEvenFill):
"""Set the underlying :class:`~QtGui.QPainterPath` to the specified
:class:`~QtCore.Qt.FillRule`
This can be useful for allowing in the filling of voids.
Parameters
----------
fillRule : QtCore.Qt.FillRule
A member of the :class:`~QtCore.Qt.FillRule` enum
"""
self._fillRule = fillRule
self.updatePath()
[docs]
def setBrush(self, *args, **kwds):
"""Change the fill brush. Accepts the same arguments as :func:`~pyqtgraph.mkBrush`
"""
QtWidgets.QGraphicsPathItem.setBrush(self, fn.mkBrush(*args, **kwds))
[docs]
def setPen(self, *args, **kwds):
"""Change the fill pen. Accepts the same arguments as :func:`~pyqtgraph.mkColor`
"""
QtWidgets.QGraphicsPathItem.setPen(self, fn.mkPen(*args, **kwds))
[docs]
def setCurves(
self,
curve1: Union[PlotDataItem, PlotCurveItem],
curve2: Union[PlotDataItem, PlotCurveItem]
):
"""Method to set the Curves to draw the FillBetweenItem between
Parameters
----------
curve1 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
Line to draw fill from
curve2 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
Line to draw fill to
Raises
------
TypeError
Raised when input arguments are not either :class:`~pyqtgraph.PlotDataItem` or
:class:`~pyqtgraph.PlotCurveItem`
"""
if self.curves is not None:
for c in self.curves:
try:
c.sigPlotChanged.disconnect(self.curveChanged)
except (TypeError, RuntimeError):
pass
curves = [curve1, curve2]
for c in curves:
if not isinstance(c, (PlotDataItem, PlotCurveItem)):
raise TypeError("Curves must be PlotDataItem or PlotCurveItem.")
self.curves = curves
curve1.sigPlotChanged.connect(self.curveChanged)
curve2.sigPlotChanged.connect(self.curveChanged)
self.setZValue(min(curve1.zValue(), curve2.zValue())-1)
self.curveChanged()
def curveChanged(self):
self.updatePath()
def updatePath(self):
if self.curves is None:
self.setPath(QtGui.QPainterPath())
return
paths = []
for c in self.curves:
if isinstance(c, PlotDataItem):
paths.append(c.curve.getPath())
elif isinstance(c, PlotCurveItem):
paths.append(c.getPath())
path = QtGui.QPainterPath()
path.setFillRule(self.fillRule())
ps1 = paths[0].toSubpathPolygons()
ps2 = paths[1].toReversed().toSubpathPolygons()
ps2.reverse()
if len(ps1) == 0 or len(ps2) == 0:
self.setPath(QtGui.QPainterPath())
return
for p1, p2 in zip(ps1, ps2):
path.addPolygon(p1 + p2)
self.setPath(path)