1
+ from typing import Union
2
+
1
3
from .. import functions as fn
2
- from ..Qt import QtGui , QtWidgets
4
+ from ..Qt import QtGui , QtWidgets , QtCore
3
5
from .PlotCurveItem import PlotCurveItem
4
6
from .PlotDataItem import PlotDataItem
5
7
@@ -9,33 +11,104 @@ class FillBetweenItem(QtWidgets.QGraphicsPathItem):
9
11
"""
10
12
GraphicsItem filling the space between two PlotDataItems.
11
13
"""
12
- def __init__ (self , curve1 = None , curve2 = None , brush = None , pen = None ):
13
- QtWidgets .QGraphicsPathItem .__init__ (self )
14
+ def __init__ (
15
+ self ,
16
+ curve1 : Union [PlotDataItem , PlotCurveItem ],
17
+ curve2 : Union [PlotDataItem , PlotCurveItem ],
18
+ brush = None ,
19
+ pen = None ,
20
+ fillRule : QtCore .Qt .FillRule = QtCore .Qt .FillRule .OddEvenFill
21
+ ):
22
+ """FillBetweenItem fills a region between two curves with a specified
23
+ :class:`~QtGui.QBrush`.
24
+
25
+ Parameters
26
+ ----------
27
+ curve1 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
28
+ Line to draw fill from
29
+ curve2 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
30
+ Line to draw fill to
31
+ brush : color_like, optional
32
+ Arguments accepted by :func:`~pyqtgraph.mkBrush`, used
33
+ to create the :class:`~QtGui.QBrush` instance used to draw the item
34
+ by default None
35
+ pen : color_like, optional
36
+ Arguments accepted by :func:`~pyqtgraph.mkColor`, used
37
+ to create the :class:`~QtGui.QPen` instance used to draw the item
38
+ by default ``None``
39
+ fillRule : QtCore.Qt.FillRule, optional
40
+ FillRule to be applied to the underlying :class:`~QtGui.QPainterPath`
41
+ instance, by default ``QtCore.Qt.FillRule.OddEvenFill``
42
+
43
+ Raises
44
+ ------
45
+ ValueError
46
+ Raised when ``None`` is passed in as either ``curve1``
47
+ or ``curve2``
48
+ TypeError
49
+ Raised when either ``curve1`` or ``curve2`` is not either
50
+ :class:`~pyqtgraph.PlotDataItem` or :class:`~pyqtgraph.PlotCurveItem`
51
+ """
52
+ super ().__init__ ()
14
53
self .curves = None
54
+ self ._fillRule = fillRule
15
55
if curve1 is not None and curve2 is not None :
16
56
self .setCurves (curve1 , curve2 )
17
57
elif curve1 is not None or curve2 is not None :
18
- raise Exception ("Must specify two curves to fill between." )
58
+ raise ValueError ("Must specify two curves to fill between." )
19
59
20
60
if brush is not None :
21
61
self .setBrush (brush )
22
62
self .setPen (pen )
23
63
self .updatePath ()
64
+
65
+ def fillRule (self ):
66
+ return self ._fillRule
67
+
68
+ def setFillRule (self , fillRule : QtCore .Qt .FillRule = QtCore .Qt .FillRule .OddEvenFill ):
69
+ """Set the underlying :class:`~QtGui.QPainterPath` to the specified
70
+ :class:`~QtCore.Qt.FillRule`
71
+
72
+ This can be useful for allowing in the filling of voids.
73
+
74
+ Parameters
75
+ ----------
76
+ fillRule : QtCore.Qt.FillRule
77
+ A member of the :class:`~QtCore.Qt.FillRule` enum
78
+ """
79
+ self ._fillRule = fillRule
80
+ self .updatePath ()
24
81
25
82
def setBrush (self , * args , ** kwds ):
26
- """Change the fill brush. Accepts the same arguments as pg.mkBrush()"""
83
+ """Change the fill brush. Accepts the same arguments as :func:`~pyqtgraph.mkBrush`
84
+ """
27
85
QtWidgets .QGraphicsPathItem .setBrush (self , fn .mkBrush (* args , ** kwds ))
28
86
29
87
def setPen (self , * args , ** kwds ):
88
+ """Change the fill pen. Accepts the same arguments as :func:`~pyqtgraph.mkColor`
89
+ """
30
90
QtWidgets .QGraphicsPathItem .setPen (self , fn .mkPen (* args , ** kwds ))
31
91
32
- def setCurves (self , curve1 , curve2 ):
33
- """Set the curves to fill between.
34
-
35
- Arguments must be instances of PlotDataItem or PlotCurveItem.
36
-
37
- Added in version 0.9.9
38
- """
92
+ def setCurves (
93
+ self ,
94
+ curve1 : Union [PlotDataItem , PlotCurveItem ],
95
+ curve2 : Union [PlotDataItem , PlotCurveItem ]
96
+ ):
97
+ """Method to set the Curves to draw the FillBetweenItem between
98
+
99
+ Parameters
100
+ ----------
101
+ curve1 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
102
+ Line to draw fill from
103
+ curve2 : :class:`~pyqtgraph.PlotDataItem` | :class:`~pyqtgraph.PlotCurveItem`
104
+ Line to draw fill to
105
+
106
+ Raises
107
+ ------
108
+ TypeError
109
+ Raised when input arguments are not either :class:`~pyqtgraph.PlotDataItem` or
110
+ :class:`~pyqtgraph.PlotCurveItem`
111
+ """
39
112
if self .curves is not None :
40
113
for c in self .curves :
41
114
try :
@@ -45,7 +118,7 @@ def setCurves(self, curve1, curve2):
45
118
46
119
curves = [curve1 , curve2 ]
47
120
for c in curves :
48
- if not isinstance (c , PlotDataItem ) and not isinstance ( c , PlotCurveItem ):
121
+ if not isinstance (c , ( PlotDataItem , PlotCurveItem ) ):
49
122
raise TypeError ("Curves must be PlotDataItem or PlotCurveItem." )
50
123
self .curves = curves
51
124
curve1 .sigPlotChanged .connect (self .curveChanged )
@@ -55,6 +128,7 @@ def setCurves(self, curve1, curve2):
55
128
56
129
def curveChanged (self ):
57
130
self .updatePath ()
131
+
58
132
def updatePath (self ):
59
133
if self .curves is None :
60
134
self .setPath (QtGui .QPainterPath ())
@@ -67,19 +141,17 @@ def updatePath(self):
67
141
paths .append (c .getPath ())
68
142
69
143
path = QtGui .QPainterPath ()
70
- transform = QtGui . QTransform ()
144
+ path . setFillRule ( self . fillRule ())
71
145
72
- ps1 = paths [0 ].toSubpathPolygons (transform )
73
- ps2 = paths [1 ].toReversed ().toSubpathPolygons (transform )
146
+ ps1 = paths [0 ].toSubpathPolygons ()
147
+ ps2 = paths [1 ].toReversed ().toSubpathPolygons ()
74
148
ps2 .reverse ()
75
149
76
150
if len (ps1 ) == 0 or len (ps2 ) == 0 :
77
151
self .setPath (QtGui .QPainterPath ())
78
152
return
79
-
153
+
80
154
for p1 , p2 in zip (ps1 , ps2 ):
81
- intersection = p1 .intersected (p2 )
82
- if not intersection .isEmpty ():
83
- path .addPolygon (intersection )
84
- path .addPolygon (p1 + p2 )
155
+ path .addPolygon (p1 + p2 )
156
+
85
157
self .setPath (path )
0 commit comments