Merge pull request #568 from acq4/linearregion-updates
Linearregion updates
This commit is contained in:
commit
d7d2d5ac9e
|
@ -31,7 +31,8 @@ class InfiniteLine(GraphicsObject):
|
||||||
sigPositionChanged = QtCore.Signal(object)
|
sigPositionChanged = QtCore.Signal(object)
|
||||||
|
|
||||||
def __init__(self, pos=None, angle=90, pen=None, movable=False, bounds=None,
|
def __init__(self, pos=None, angle=90, pen=None, movable=False, bounds=None,
|
||||||
hoverPen=None, label=None, labelOpts=None, name=None):
|
hoverPen=None, label=None, labelOpts=None, span=(0, 1), markers=None,
|
||||||
|
name=None):
|
||||||
"""
|
"""
|
||||||
=============== ==================================================================
|
=============== ==================================================================
|
||||||
**Arguments:**
|
**Arguments:**
|
||||||
|
@ -41,22 +42,28 @@ class InfiniteLine(GraphicsObject):
|
||||||
pen Pen to use when drawing line. Can be any arguments that are valid
|
pen Pen to use when drawing line. Can be any arguments that are valid
|
||||||
for :func:`mkPen <pyqtgraph.mkPen>`. Default pen is transparent
|
for :func:`mkPen <pyqtgraph.mkPen>`. Default pen is transparent
|
||||||
yellow.
|
yellow.
|
||||||
|
hoverPen Pen to use when the mouse cursor hovers over the line.
|
||||||
|
Only used when movable=True.
|
||||||
movable If True, the line can be dragged to a new position by the user.
|
movable If True, the line can be dragged to a new position by the user.
|
||||||
|
bounds Optional [min, max] bounding values. Bounds are only valid if the
|
||||||
|
line is vertical or horizontal.
|
||||||
hoverPen Pen to use when drawing line when hovering over it. Can be any
|
hoverPen Pen to use when drawing line when hovering over it. Can be any
|
||||||
arguments that are valid for :func:`mkPen <pyqtgraph.mkPen>`.
|
arguments that are valid for :func:`mkPen <pyqtgraph.mkPen>`.
|
||||||
Default pen is red.
|
Default pen is red.
|
||||||
bounds Optional [min, max] bounding values. Bounds are only valid if the
|
|
||||||
line is vertical or horizontal.
|
|
||||||
label Text to be displayed in a label attached to the line, or
|
label Text to be displayed in a label attached to the line, or
|
||||||
None to show no label (default is None). May optionally
|
None to show no label (default is None). May optionally
|
||||||
include formatting strings to display the line value.
|
include formatting strings to display the line value.
|
||||||
labelOpts A dict of keyword arguments to use when constructing the
|
labelOpts A dict of keyword arguments to use when constructing the
|
||||||
text label. See :class:`InfLineLabel`.
|
text label. See :class:`InfLineLabel`.
|
||||||
|
span Optional tuple (min, max) giving the range over the view to draw
|
||||||
|
the line. For example, with a vertical line, use span=(0.5, 1)
|
||||||
|
to draw only on the top half of the view.
|
||||||
|
markers List of (marker, position, size) tuples, one per marker to display
|
||||||
|
on the line. See the addMarker method.
|
||||||
name Name of the item
|
name Name of the item
|
||||||
=============== ==================================================================
|
=============== ==================================================================
|
||||||
"""
|
"""
|
||||||
self._boundingRect = None
|
self._boundingRect = None
|
||||||
self._line = None
|
|
||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
|
|
||||||
|
@ -79,12 +86,26 @@ class InfiniteLine(GraphicsObject):
|
||||||
if pen is None:
|
if pen is None:
|
||||||
pen = (200, 200, 100)
|
pen = (200, 200, 100)
|
||||||
self.setPen(pen)
|
self.setPen(pen)
|
||||||
|
|
||||||
if hoverPen is None:
|
if hoverPen is None:
|
||||||
self.setHoverPen(color=(255,0,0), width=self.pen.width())
|
self.setHoverPen(color=(255,0,0), width=self.pen.width())
|
||||||
else:
|
else:
|
||||||
self.setHoverPen(hoverPen)
|
self.setHoverPen(hoverPen)
|
||||||
|
|
||||||
|
self.span = span
|
||||||
self.currentPen = self.pen
|
self.currentPen = self.pen
|
||||||
|
|
||||||
|
self.markers = []
|
||||||
|
self._maxMarkerSize = 0
|
||||||
|
if markers is not None:
|
||||||
|
for m in markers:
|
||||||
|
self.addMarker(*m)
|
||||||
|
|
||||||
|
# Cache variables for managing bounds
|
||||||
|
self._endPoints = [0, 1] #
|
||||||
|
self._bounds = None
|
||||||
|
self._lastViewSize = None
|
||||||
|
|
||||||
if label is not None:
|
if label is not None:
|
||||||
labelOpts = {} if labelOpts is None else labelOpts
|
labelOpts = {} if labelOpts is None else labelOpts
|
||||||
self.label = InfLineLabel(self, text=label, **labelOpts)
|
self.label = InfLineLabel(self, text=label, **labelOpts)
|
||||||
|
@ -99,6 +120,11 @@ class InfiniteLine(GraphicsObject):
|
||||||
self.maxRange = bounds
|
self.maxRange = bounds
|
||||||
self.setValue(self.value())
|
self.setValue(self.value())
|
||||||
|
|
||||||
|
def bounds(self):
|
||||||
|
"""Return the (minimum, maximum) values allowed when dragging.
|
||||||
|
"""
|
||||||
|
return self.maxRange[:]
|
||||||
|
|
||||||
def setPen(self, *args, **kwargs):
|
def setPen(self, *args, **kwargs):
|
||||||
"""Set the pen for drawing the line. Allowable arguments are any that are valid
|
"""Set the pen for drawing the line. Allowable arguments are any that are valid
|
||||||
for :func:`mkPen <pyqtgraph.mkPen>`."""
|
for :func:`mkPen <pyqtgraph.mkPen>`."""
|
||||||
|
@ -115,11 +141,70 @@ class InfiniteLine(GraphicsObject):
|
||||||
If the line is not movable, then hovering is also disabled.
|
If the line is not movable, then hovering is also disabled.
|
||||||
|
|
||||||
Added in version 0.9.9."""
|
Added in version 0.9.9."""
|
||||||
|
# If user did not supply a width, then copy it from pen
|
||||||
|
widthSpecified = ((len(args) == 1 and
|
||||||
|
(isinstance(args[0], QtGui.QPen) or
|
||||||
|
(isinstance(args[0], dict) and 'width' in args[0]))
|
||||||
|
) or 'width' in kwargs)
|
||||||
self.hoverPen = fn.mkPen(*args, **kwargs)
|
self.hoverPen = fn.mkPen(*args, **kwargs)
|
||||||
|
if not widthSpecified:
|
||||||
|
self.hoverPen.setWidth(self.pen.width())
|
||||||
|
|
||||||
if self.mouseHovering:
|
if self.mouseHovering:
|
||||||
self.currentPen = self.hoverPen
|
self.currentPen = self.hoverPen
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def addMarker(self, marker, position=0.5, size=10.0):
|
||||||
|
"""Add a marker to be displayed on the line.
|
||||||
|
|
||||||
|
============= =========================================================
|
||||||
|
**Arguments**
|
||||||
|
marker String indicating the style of marker to add:
|
||||||
|
'<|', '|>', '>|', '|<', '<|>', '>|<', '^', 'v', 'o'
|
||||||
|
position Position (0.0-1.0) along the visible extent of the line
|
||||||
|
to place the marker. Default is 0.5.
|
||||||
|
size Size of the marker in pixels. Default is 10.0.
|
||||||
|
============= =========================================================
|
||||||
|
"""
|
||||||
|
path = QtGui.QPainterPath()
|
||||||
|
if marker == 'o':
|
||||||
|
path.addEllipse(QtCore.QRectF(-0.5, -0.5, 1, 1))
|
||||||
|
if '<|' in marker:
|
||||||
|
p = QtGui.QPolygonF([Point(0.5, 0), Point(0, -0.5), Point(-0.5, 0)])
|
||||||
|
path.addPolygon(p)
|
||||||
|
path.closeSubpath()
|
||||||
|
if '|>' in marker:
|
||||||
|
p = QtGui.QPolygonF([Point(0.5, 0), Point(0, 0.5), Point(-0.5, 0)])
|
||||||
|
path.addPolygon(p)
|
||||||
|
path.closeSubpath()
|
||||||
|
if '>|' in marker:
|
||||||
|
p = QtGui.QPolygonF([Point(0.5, -0.5), Point(0, 0), Point(-0.5, -0.5)])
|
||||||
|
path.addPolygon(p)
|
||||||
|
path.closeSubpath()
|
||||||
|
if '|<' in marker:
|
||||||
|
p = QtGui.QPolygonF([Point(0.5, 0.5), Point(0, 0), Point(-0.5, 0.5)])
|
||||||
|
path.addPolygon(p)
|
||||||
|
path.closeSubpath()
|
||||||
|
if '^' in marker:
|
||||||
|
p = QtGui.QPolygonF([Point(0, -0.5), Point(0.5, 0), Point(0, 0.5)])
|
||||||
|
path.addPolygon(p)
|
||||||
|
path.closeSubpath()
|
||||||
|
if 'v' in marker:
|
||||||
|
p = QtGui.QPolygonF([Point(0, -0.5), Point(-0.5, 0), Point(0, 0.5)])
|
||||||
|
path.addPolygon(p)
|
||||||
|
path.closeSubpath()
|
||||||
|
|
||||||
|
self.markers.append((path, position, size))
|
||||||
|
self._maxMarkerSize = max([m[2] / 2. for m in self.markers])
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def clearMarkers(self):
|
||||||
|
""" Remove all markers from this line.
|
||||||
|
"""
|
||||||
|
self.markers = []
|
||||||
|
self._maxMarkerSize = 0
|
||||||
|
self.update()
|
||||||
|
|
||||||
def setAngle(self, angle):
|
def setAngle(self, angle):
|
||||||
"""
|
"""
|
||||||
Takes angle argument in degrees.
|
Takes angle argument in degrees.
|
||||||
|
@ -128,7 +213,7 @@ class InfiniteLine(GraphicsObject):
|
||||||
Note that the use of value() and setValue() changes if the line is
|
Note that the use of value() and setValue() changes if the line is
|
||||||
not vertical or horizontal.
|
not vertical or horizontal.
|
||||||
"""
|
"""
|
||||||
self.angle = ((angle+45) % 180) - 45 ## -45 <= angle < 135
|
self.angle = angle #((angle+45) % 180) - 45 ## -45 <= angle < 135
|
||||||
self.resetTransform()
|
self.resetTransform()
|
||||||
self.rotate(self.angle)
|
self.rotate(self.angle)
|
||||||
self.update()
|
self.update()
|
||||||
|
@ -200,33 +285,96 @@ class InfiniteLine(GraphicsObject):
|
||||||
#print "ignore", change
|
#print "ignore", change
|
||||||
#return GraphicsObject.itemChange(self, change, val)
|
#return GraphicsObject.itemChange(self, change, val)
|
||||||
|
|
||||||
|
def setSpan(self, mn, mx):
|
||||||
|
if self.span != (mn, mx):
|
||||||
|
self.span = (mn, mx)
|
||||||
|
self.update()
|
||||||
|
|
||||||
def _invalidateCache(self):
|
def _invalidateCache(self):
|
||||||
self._line = None
|
|
||||||
self._boundingRect = None
|
self._boundingRect = None
|
||||||
|
|
||||||
def boundingRect(self):
|
def _computeBoundingRect(self):
|
||||||
if self._boundingRect is None:
|
|
||||||
#br = UIGraphicsItem.boundingRect(self)
|
#br = UIGraphicsItem.boundingRect(self)
|
||||||
br = self.viewRect()
|
vr = self.viewRect() # bounds of containing ViewBox mapped to local coords.
|
||||||
if br is None:
|
if vr is None:
|
||||||
return QtCore.QRectF()
|
return QtCore.QRectF()
|
||||||
|
|
||||||
## add a 4-pixel radius around the line for mouse interaction.
|
## add a 4-pixel radius around the line for mouse interaction.
|
||||||
|
|
||||||
px = self.pixelLength(direction=Point(1,0), ortho=True) ## get pixel length orthogonal to the line
|
px = self.pixelLength(direction=Point(1,0), ortho=True) ## get pixel length orthogonal to the line
|
||||||
if px is None:
|
if px is None:
|
||||||
px = 0
|
px = 0
|
||||||
w = (max(4, self.pen.width()/2, self.hoverPen.width()/2)+1) * px
|
pw = max(self.pen.width() / 2, self.hoverPen.width() / 2)
|
||||||
|
w = max(4, self._maxMarkerSize + pw) + 1
|
||||||
|
w = w * px
|
||||||
|
br = QtCore.QRectF(vr)
|
||||||
br.setBottom(-w)
|
br.setBottom(-w)
|
||||||
br.setTop(w)
|
br.setTop(w)
|
||||||
|
|
||||||
|
length = br.width()
|
||||||
|
left = br.left() + length * self.span[0]
|
||||||
|
right = br.left() + length * self.span[1]
|
||||||
|
br.setLeft(left - w)
|
||||||
|
br.setRight(right + w)
|
||||||
br = br.normalized()
|
br = br.normalized()
|
||||||
self._boundingRect = br
|
|
||||||
self._line = QtCore.QLineF(br.right(), 0.0, br.left(), 0.0)
|
vs = self.getViewBox().size()
|
||||||
|
|
||||||
|
if self._bounds != br or self._lastViewSize != vs:
|
||||||
|
self._bounds = br
|
||||||
|
self._lastViewSize = vs
|
||||||
|
self.prepareGeometryChange()
|
||||||
|
|
||||||
|
self._endPoints = (left, right)
|
||||||
|
self._lastViewRect = vr
|
||||||
|
|
||||||
|
return self._bounds
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
if self._boundingRect is None:
|
||||||
|
self._boundingRect = self._computeBoundingRect()
|
||||||
return self._boundingRect
|
return self._boundingRect
|
||||||
|
|
||||||
def paint(self, p, *args):
|
def paint(self, p, *args):
|
||||||
p.setPen(self.currentPen)
|
p.setRenderHint(p.Antialiasing)
|
||||||
p.drawLine(self._line)
|
|
||||||
|
left, right = self._endPoints
|
||||||
|
pen = self.currentPen
|
||||||
|
pen.setJoinStyle(QtCore.Qt.MiterJoin)
|
||||||
|
p.setPen(pen)
|
||||||
|
p.drawLine(Point(left, 0), Point(right, 0))
|
||||||
|
|
||||||
|
|
||||||
|
if len(self.markers) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
# paint markers in native coordinate system
|
||||||
|
tr = p.transform()
|
||||||
|
p.resetTransform()
|
||||||
|
|
||||||
|
start = tr.map(Point(left, 0))
|
||||||
|
end = tr.map(Point(right, 0))
|
||||||
|
up = tr.map(Point(left, 1))
|
||||||
|
dif = end - start
|
||||||
|
length = Point(dif).length()
|
||||||
|
angle = np.arctan2(dif.y(), dif.x()) * 180 / np.pi
|
||||||
|
|
||||||
|
p.translate(start)
|
||||||
|
p.rotate(angle)
|
||||||
|
|
||||||
|
up = up - start
|
||||||
|
det = up.x() * dif.y() - dif.x() * up.y()
|
||||||
|
p.scale(1, 1 if det > 0 else -1)
|
||||||
|
|
||||||
|
p.setBrush(fn.mkBrush(self.currentPen.color()))
|
||||||
|
#p.setPen(fn.mkPen(None))
|
||||||
|
tr = p.transform()
|
||||||
|
for path, pos, size in self.markers:
|
||||||
|
p.setTransform(tr)
|
||||||
|
x = length * pos
|
||||||
|
p.translate(x, 0)
|
||||||
|
p.scale(size, size)
|
||||||
|
p.drawPath(path)
|
||||||
|
|
||||||
def dataBounds(self, axis, frac=1.0, orthoRange=None):
|
def dataBounds(self, axis, frac=1.0, orthoRange=None):
|
||||||
if axis == 0:
|
if axis == 0:
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
from ..Qt import QtGui, QtCore
|
from ..Qt import QtGui, QtCore
|
||||||
from .UIGraphicsItem import UIGraphicsItem
|
from .GraphicsObject import GraphicsObject
|
||||||
from .InfiniteLine import InfiniteLine
|
from .InfiniteLine import InfiniteLine
|
||||||
from .. import functions as fn
|
from .. import functions as fn
|
||||||
from .. import debug as debug
|
from .. import debug as debug
|
||||||
|
|
||||||
__all__ = ['LinearRegionItem']
|
__all__ = ['LinearRegionItem']
|
||||||
|
|
||||||
class LinearRegionItem(UIGraphicsItem):
|
class LinearRegionItem(GraphicsObject):
|
||||||
"""
|
"""
|
||||||
**Bases:** :class:`UIGraphicsItem <pyqtgraph.UIGraphicsItem>`
|
**Bases:** :class:`GraphicsObject <pyqtgraph.GraphicsObject>`
|
||||||
|
|
||||||
Used for marking a horizontal or vertical region in plots.
|
Used for marking a horizontal or vertical region in plots.
|
||||||
The region can be dragged and is bounded by lines which can be dragged individually.
|
The region can be dragged and is bounded by lines which can be dragged individually.
|
||||||
|
@ -26,65 +26,110 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
sigRegionChanged = QtCore.Signal(object)
|
sigRegionChanged = QtCore.Signal(object)
|
||||||
Vertical = 0
|
Vertical = 0
|
||||||
Horizontal = 1
|
Horizontal = 1
|
||||||
|
_orientation_axis = {
|
||||||
|
Vertical: 0,
|
||||||
|
Horizontal: 1,
|
||||||
|
'vertical': 0,
|
||||||
|
'horizontal': 1,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, values=[0,1], orientation=None, brush=None, movable=True, bounds=None):
|
def __init__(self, values=(0, 1), orientation='vertical', brush=None, pen=None,
|
||||||
|
hoverBrush=None, hoverPen=None, movable=True, bounds=None,
|
||||||
|
span=(0, 1), swapMode='sort'):
|
||||||
"""Create a new LinearRegionItem.
|
"""Create a new LinearRegionItem.
|
||||||
|
|
||||||
============== =====================================================================
|
============== =====================================================================
|
||||||
**Arguments:**
|
**Arguments:**
|
||||||
values A list of the positions of the lines in the region. These are not
|
values A list of the positions of the lines in the region. These are not
|
||||||
limits; limits can be set by specifying bounds.
|
limits; limits can be set by specifying bounds.
|
||||||
orientation Options are LinearRegionItem.Vertical or LinearRegionItem.Horizontal.
|
orientation Options are 'vertical' or 'horizontal', indicating the
|
||||||
If not specified it will be vertical.
|
The default is 'vertical', indicating that the
|
||||||
brush Defines the brush that fills the region. Can be any arguments that
|
brush Defines the brush that fills the region. Can be any arguments that
|
||||||
are valid for :func:`mkBrush <pyqtgraph.mkBrush>`. Default is
|
are valid for :func:`mkBrush <pyqtgraph.mkBrush>`. Default is
|
||||||
transparent blue.
|
transparent blue.
|
||||||
|
pen The pen to use when drawing the lines that bound the region.
|
||||||
|
hoverBrush The brush to use when the mouse is hovering over the region.
|
||||||
|
hoverPen The pen to use when the mouse is hovering over the region.
|
||||||
movable If True, the region and individual lines are movable by the user; if
|
movable If True, the region and individual lines are movable by the user; if
|
||||||
False, they are static.
|
False, they are static.
|
||||||
bounds Optional [min, max] bounding values for the region
|
bounds Optional [min, max] bounding values for the region
|
||||||
|
span Optional [min, max] giving the range over the view to draw
|
||||||
|
the region. For example, with a vertical line, use span=(0.5, 1)
|
||||||
|
to draw only on the top half of the view.
|
||||||
|
swapMode Sets the behavior of the region when the lines are moved such that
|
||||||
|
their order reverses:
|
||||||
|
* "block" means the user cannot drag one line past the other
|
||||||
|
* "push" causes both lines to be moved if one would cross the other
|
||||||
|
* "sort" means that lines may trade places, but the output of
|
||||||
|
getRegion always gives the line positions in ascending order.
|
||||||
|
* None means that no attempt is made to handle swapped line
|
||||||
|
positions.
|
||||||
|
The default is "sort".
|
||||||
============== =====================================================================
|
============== =====================================================================
|
||||||
"""
|
"""
|
||||||
|
|
||||||
UIGraphicsItem.__init__(self)
|
GraphicsObject.__init__(self)
|
||||||
if orientation is None:
|
|
||||||
orientation = LinearRegionItem.Vertical
|
|
||||||
self.orientation = orientation
|
self.orientation = orientation
|
||||||
self.bounds = QtCore.QRectF()
|
self.bounds = QtCore.QRectF()
|
||||||
self.blockLineSignal = False
|
self.blockLineSignal = False
|
||||||
self.moving = False
|
self.moving = False
|
||||||
self.mouseHovering = False
|
self.mouseHovering = False
|
||||||
|
self.span = span
|
||||||
|
self.swapMode = swapMode
|
||||||
|
self._bounds = None
|
||||||
|
|
||||||
if orientation == LinearRegionItem.Horizontal:
|
# note LinearRegionItem.Horizontal and LinearRegionItem.Vertical
|
||||||
|
# are kept for backward compatibility.
|
||||||
|
lineKwds = dict(
|
||||||
|
movable=movable,
|
||||||
|
bounds=bounds,
|
||||||
|
span=span,
|
||||||
|
pen=pen,
|
||||||
|
hoverPen=hoverPen,
|
||||||
|
)
|
||||||
|
|
||||||
|
if orientation in ('horizontal', LinearRegionItem.Horizontal):
|
||||||
self.lines = [
|
self.lines = [
|
||||||
InfiniteLine(QtCore.QPointF(0, values[0]), 0, movable=movable, bounds=bounds),
|
# rotate lines to 180 to preserve expected line orientation
|
||||||
InfiniteLine(QtCore.QPointF(0, values[1]), 0, movable=movable, bounds=bounds)]
|
# with respect to region. This ensures that placing a '<|'
|
||||||
elif orientation == LinearRegionItem.Vertical:
|
# marker on lines[0] causes it to point left in vertical mode
|
||||||
|
# and down in horizontal mode.
|
||||||
|
InfiniteLine(QtCore.QPointF(0, values[0]), angle=0, **lineKwds),
|
||||||
|
InfiniteLine(QtCore.QPointF(0, values[1]), angle=0, **lineKwds)]
|
||||||
|
self.lines[0].scale(1, -1)
|
||||||
|
self.lines[1].scale(1, -1)
|
||||||
|
elif orientation in ('vertical', LinearRegionItem.Vertical):
|
||||||
self.lines = [
|
self.lines = [
|
||||||
InfiniteLine(QtCore.QPointF(values[1], 0), 90, movable=movable, bounds=bounds),
|
InfiniteLine(QtCore.QPointF(values[0], 0), angle=90, **lineKwds),
|
||||||
InfiniteLine(QtCore.QPointF(values[0], 0), 90, movable=movable, bounds=bounds)]
|
InfiniteLine(QtCore.QPointF(values[1], 0), angle=90, **lineKwds)]
|
||||||
else:
|
else:
|
||||||
raise Exception('Orientation must be one of LinearRegionItem.Vertical or LinearRegionItem.Horizontal')
|
raise Exception("Orientation must be 'vertical' or 'horizontal'.")
|
||||||
|
|
||||||
|
|
||||||
for l in self.lines:
|
for l in self.lines:
|
||||||
l.setParentItem(self)
|
l.setParentItem(self)
|
||||||
l.sigPositionChangeFinished.connect(self.lineMoveFinished)
|
l.sigPositionChangeFinished.connect(self.lineMoveFinished)
|
||||||
l.sigPositionChanged.connect(self.lineMoved)
|
self.lines[0].sigPositionChanged.connect(lambda: self.lineMoved(0))
|
||||||
|
self.lines[1].sigPositionChanged.connect(lambda: self.lineMoved(1))
|
||||||
|
|
||||||
if brush is None:
|
if brush is None:
|
||||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 255, 50))
|
brush = QtGui.QBrush(QtGui.QColor(0, 0, 255, 50))
|
||||||
self.setBrush(brush)
|
self.setBrush(brush)
|
||||||
|
|
||||||
|
if hoverBrush is None:
|
||||||
|
c = self.brush.color()
|
||||||
|
c.setAlpha(min(c.alpha() * 2, 255))
|
||||||
|
hoverBrush = fn.mkBrush(c)
|
||||||
|
self.setHoverBrush(hoverBrush)
|
||||||
|
|
||||||
self.setMovable(movable)
|
self.setMovable(movable)
|
||||||
|
|
||||||
def getRegion(self):
|
def getRegion(self):
|
||||||
"""Return the values at the edges of the region."""
|
"""Return the values at the edges of the region."""
|
||||||
#if self.orientation[0] == 'h':
|
r = (self.lines[0].value(), self.lines[1].value())
|
||||||
#r = (self.bounds.top(), self.bounds.bottom())
|
if self.swapMode == 'sort':
|
||||||
#else:
|
|
||||||
#r = (self.bounds.left(), self.bounds.right())
|
|
||||||
r = [self.lines[0].value(), self.lines[1].value()]
|
|
||||||
return (min(r), max(r))
|
return (min(r), max(r))
|
||||||
|
else:
|
||||||
|
return r
|
||||||
|
|
||||||
def setRegion(self, rgn):
|
def setRegion(self, rgn):
|
||||||
"""Set the values for the edges of the region.
|
"""Set the values for the edges of the region.
|
||||||
|
@ -101,7 +146,8 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
self.blockLineSignal = False
|
self.blockLineSignal = False
|
||||||
self.lines[1].setValue(rgn[1])
|
self.lines[1].setValue(rgn[1])
|
||||||
#self.blockLineSignal = False
|
#self.blockLineSignal = False
|
||||||
self.lineMoved()
|
self.lineMoved(0)
|
||||||
|
self.lineMoved(1)
|
||||||
self.lineMoveFinished()
|
self.lineMoveFinished()
|
||||||
|
|
||||||
def setBrush(self, *br, **kargs):
|
def setBrush(self, *br, **kargs):
|
||||||
|
@ -111,6 +157,13 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
self.brush = fn.mkBrush(*br, **kargs)
|
self.brush = fn.mkBrush(*br, **kargs)
|
||||||
self.currentBrush = self.brush
|
self.currentBrush = self.brush
|
||||||
|
|
||||||
|
def setHoverBrush(self, *br, **kargs):
|
||||||
|
"""Set the brush that fills the region when the mouse is hovering over.
|
||||||
|
Can have any arguments that are valid
|
||||||
|
for :func:`mkBrush <pyqtgraph.mkBrush>`.
|
||||||
|
"""
|
||||||
|
self.hoverBrush = fn.mkBrush(*br, **kargs)
|
||||||
|
|
||||||
def setBounds(self, bounds):
|
def setBounds(self, bounds):
|
||||||
"""Optional [min, max] bounding values for the region. To have no bounds on the
|
"""Optional [min, max] bounding values for the region. To have no bounds on the
|
||||||
region use [None, None].
|
region use [None, None].
|
||||||
|
@ -128,82 +181,68 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
self.movable = m
|
self.movable = m
|
||||||
self.setAcceptHoverEvents(m)
|
self.setAcceptHoverEvents(m)
|
||||||
|
|
||||||
|
def setSpan(self, mn, mx):
|
||||||
|
if self.span == (mn, mx):
|
||||||
|
return
|
||||||
|
self.span = (mn, mx)
|
||||||
|
self.lines[0].setSpan(mn, mx)
|
||||||
|
self.lines[1].setSpan(mn, mx)
|
||||||
|
self.update()
|
||||||
|
|
||||||
def boundingRect(self):
|
def boundingRect(self):
|
||||||
br = UIGraphicsItem.boundingRect(self)
|
br = self.viewRect() # bounds of containing ViewBox mapped to local coords.
|
||||||
|
|
||||||
rng = self.getRegion()
|
rng = self.getRegion()
|
||||||
if self.orientation == LinearRegionItem.Vertical:
|
if self.orientation in ('vertical', LinearRegionItem.Vertical):
|
||||||
br.setLeft(rng[0])
|
br.setLeft(rng[0])
|
||||||
br.setRight(rng[1])
|
br.setRight(rng[1])
|
||||||
|
length = br.height()
|
||||||
|
br.setBottom(br.top() + length * self.span[1])
|
||||||
|
br.setTop(br.top() + length * self.span[0])
|
||||||
else:
|
else:
|
||||||
br.setTop(rng[0])
|
br.setTop(rng[0])
|
||||||
br.setBottom(rng[1])
|
br.setBottom(rng[1])
|
||||||
return br.normalized()
|
length = br.width()
|
||||||
|
br.setRight(br.left() + length * self.span[1])
|
||||||
|
br.setLeft(br.left() + length * self.span[0])
|
||||||
|
|
||||||
|
br = br.normalized()
|
||||||
|
|
||||||
|
if self._bounds != br:
|
||||||
|
self._bounds = br
|
||||||
|
self.prepareGeometryChange()
|
||||||
|
|
||||||
|
return br
|
||||||
|
|
||||||
def paint(self, p, *args):
|
def paint(self, p, *args):
|
||||||
profiler = debug.Profiler()
|
profiler = debug.Profiler()
|
||||||
UIGraphicsItem.paint(self, p, *args)
|
|
||||||
p.setBrush(self.currentBrush)
|
p.setBrush(self.currentBrush)
|
||||||
p.setPen(fn.mkPen(None))
|
p.setPen(fn.mkPen(None))
|
||||||
p.drawRect(self.boundingRect())
|
p.drawRect(self.boundingRect())
|
||||||
|
|
||||||
def dataBounds(self, axis, frac=1.0, orthoRange=None):
|
def dataBounds(self, axis, frac=1.0, orthoRange=None):
|
||||||
if axis == self.orientation:
|
if axis == self._orientation_axis[self.orientation]:
|
||||||
return self.getRegion()
|
return self.getRegion()
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def lineMoved(self):
|
def lineMoved(self, i):
|
||||||
if self.blockLineSignal:
|
if self.blockLineSignal:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# lines swapped
|
||||||
|
if self.lines[0].value() > self.lines[1].value():
|
||||||
|
if self.swapMode == 'block':
|
||||||
|
self.lines[i].setValue(self.lines[1-i].value())
|
||||||
|
elif self.swapMode == 'push':
|
||||||
|
self.lines[1-i].setValue(self.lines[i].value())
|
||||||
|
|
||||||
self.prepareGeometryChange()
|
self.prepareGeometryChange()
|
||||||
#self.emit(QtCore.SIGNAL('regionChanged'), self)
|
|
||||||
self.sigRegionChanged.emit(self)
|
self.sigRegionChanged.emit(self)
|
||||||
|
|
||||||
def lineMoveFinished(self):
|
def lineMoveFinished(self):
|
||||||
#self.emit(QtCore.SIGNAL('regionChangeFinished'), self)
|
|
||||||
self.sigRegionChangeFinished.emit(self)
|
self.sigRegionChangeFinished.emit(self)
|
||||||
|
|
||||||
|
|
||||||
#def updateBounds(self):
|
|
||||||
#vb = self.view().viewRect()
|
|
||||||
#vals = [self.lines[0].value(), self.lines[1].value()]
|
|
||||||
#if self.orientation[0] == 'h':
|
|
||||||
#vb.setTop(min(vals))
|
|
||||||
#vb.setBottom(max(vals))
|
|
||||||
#else:
|
|
||||||
#vb.setLeft(min(vals))
|
|
||||||
#vb.setRight(max(vals))
|
|
||||||
#if vb != self.bounds:
|
|
||||||
#self.bounds = vb
|
|
||||||
#self.rect.setRect(vb)
|
|
||||||
|
|
||||||
#def mousePressEvent(self, ev):
|
|
||||||
#if not self.movable:
|
|
||||||
#ev.ignore()
|
|
||||||
#return
|
|
||||||
#for l in self.lines:
|
|
||||||
#l.mousePressEvent(ev) ## pass event to both lines so they move together
|
|
||||||
##if self.movable and ev.button() == QtCore.Qt.LeftButton:
|
|
||||||
##ev.accept()
|
|
||||||
##self.pressDelta = self.mapToParent(ev.pos()) - QtCore.QPointF(*self.p)
|
|
||||||
##else:
|
|
||||||
##ev.ignore()
|
|
||||||
|
|
||||||
#def mouseReleaseEvent(self, ev):
|
|
||||||
#for l in self.lines:
|
|
||||||
#l.mouseReleaseEvent(ev)
|
|
||||||
|
|
||||||
#def mouseMoveEvent(self, ev):
|
|
||||||
##print "move", ev.pos()
|
|
||||||
#if not self.movable:
|
|
||||||
#return
|
|
||||||
#self.lines[0].blockSignals(True) # only want to update once
|
|
||||||
#for l in self.lines:
|
|
||||||
#l.mouseMoveEvent(ev)
|
|
||||||
#self.lines[0].blockSignals(False)
|
|
||||||
##self.setPos(self.mapToParent(ev.pos()) - self.pressDelta)
|
|
||||||
##self.emit(QtCore.SIGNAL('dragged'), self)
|
|
||||||
|
|
||||||
def mouseDragEvent(self, ev):
|
def mouseDragEvent(self, ev):
|
||||||
if not self.movable or int(ev.button() & QtCore.Qt.LeftButton) == 0:
|
if not self.movable or int(ev.button() & QtCore.Qt.LeftButton) == 0:
|
||||||
return
|
return
|
||||||
|
@ -218,12 +257,9 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
if not self.moving:
|
if not self.moving:
|
||||||
return
|
return
|
||||||
|
|
||||||
#delta = ev.pos() - ev.lastPos()
|
|
||||||
self.lines[0].blockSignals(True) # only want to update once
|
self.lines[0].blockSignals(True) # only want to update once
|
||||||
for i, l in enumerate(self.lines):
|
for i, l in enumerate(self.lines):
|
||||||
l.setPos(self.cursorOffsets[i] + ev.pos())
|
l.setPos(self.cursorOffsets[i] + ev.pos())
|
||||||
#l.setPos(l.pos()+delta)
|
|
||||||
#l.mouseDragEvent(ev)
|
|
||||||
self.lines[0].blockSignals(False)
|
self.lines[0].blockSignals(False)
|
||||||
self.prepareGeometryChange()
|
self.prepareGeometryChange()
|
||||||
|
|
||||||
|
@ -242,7 +278,6 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
self.sigRegionChanged.emit(self)
|
self.sigRegionChanged.emit(self)
|
||||||
self.sigRegionChangeFinished.emit(self)
|
self.sigRegionChangeFinished.emit(self)
|
||||||
|
|
||||||
|
|
||||||
def hoverEvent(self, ev):
|
def hoverEvent(self, ev):
|
||||||
if self.movable and (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton):
|
if self.movable and (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton):
|
||||||
self.setMouseHover(True)
|
self.setMouseHover(True)
|
||||||
|
@ -255,36 +290,7 @@ class LinearRegionItem(UIGraphicsItem):
|
||||||
return
|
return
|
||||||
self.mouseHovering = hover
|
self.mouseHovering = hover
|
||||||
if hover:
|
if hover:
|
||||||
c = self.brush.color()
|
self.currentBrush = self.hoverBrush
|
||||||
c.setAlpha(c.alpha() * 2)
|
|
||||||
self.currentBrush = fn.mkBrush(c)
|
|
||||||
else:
|
else:
|
||||||
self.currentBrush = self.brush
|
self.currentBrush = self.brush
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
#def hoverEnterEvent(self, ev):
|
|
||||||
#print "rgn hover enter"
|
|
||||||
#ev.ignore()
|
|
||||||
#self.updateHoverBrush()
|
|
||||||
|
|
||||||
#def hoverMoveEvent(self, ev):
|
|
||||||
#print "rgn hover move"
|
|
||||||
#ev.ignore()
|
|
||||||
#self.updateHoverBrush()
|
|
||||||
|
|
||||||
#def hoverLeaveEvent(self, ev):
|
|
||||||
#print "rgn hover leave"
|
|
||||||
#ev.ignore()
|
|
||||||
#self.updateHoverBrush(False)
|
|
||||||
|
|
||||||
#def updateHoverBrush(self, hover=None):
|
|
||||||
#if hover is None:
|
|
||||||
#scene = self.scene()
|
|
||||||
#hover = scene.claimEvent(self, QtCore.Qt.LeftButton, scene.Drag)
|
|
||||||
|
|
||||||
#if hover:
|
|
||||||
#self.currentBrush = fn.mkBrush(255, 0,0,100)
|
|
||||||
#else:
|
|
||||||
#self.currentBrush = self.brush
|
|
||||||
#self.update()
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user