commit
969cdac094
125
pyqtgraph/graphicsItems/TargetItem.py
Normal file
125
pyqtgraph/graphicsItems/TargetItem.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
from ..Qt import QtGui, QtCore
|
||||||
|
import numpy as np
|
||||||
|
from ..Point import Point
|
||||||
|
from .. import functions as fn
|
||||||
|
from .GraphicsObject import GraphicsObject
|
||||||
|
from .TextItem import TextItem
|
||||||
|
|
||||||
|
|
||||||
|
class TargetItem(GraphicsObject):
|
||||||
|
"""Draws a draggable target symbol (circle plus crosshair).
|
||||||
|
|
||||||
|
The size of TargetItem will remain fixed on screen even as the view is zoomed.
|
||||||
|
Includes an optional text label.
|
||||||
|
"""
|
||||||
|
sigDragged = QtCore.Signal(object)
|
||||||
|
|
||||||
|
def __init__(self, movable=True, radii=(5, 10, 10), pen=(255, 255, 0), brush=(0, 0, 255, 100)):
|
||||||
|
GraphicsObject.__init__(self)
|
||||||
|
self._bounds = None
|
||||||
|
self._radii = radii
|
||||||
|
self._picture = None
|
||||||
|
self.movable = movable
|
||||||
|
self.moving = False
|
||||||
|
self.label = None
|
||||||
|
self.labelAngle = 0
|
||||||
|
self.pen = fn.mkPen(pen)
|
||||||
|
self.brush = fn.mkBrush(brush)
|
||||||
|
|
||||||
|
def setLabel(self, label):
|
||||||
|
if label is None:
|
||||||
|
if self.label is not None:
|
||||||
|
self.label.scene().removeItem(self.label)
|
||||||
|
self.label = None
|
||||||
|
else:
|
||||||
|
if self.label is None:
|
||||||
|
self.label = TextItem()
|
||||||
|
self.label.setParentItem(self)
|
||||||
|
self.label.setText(label)
|
||||||
|
self._updateLabel()
|
||||||
|
|
||||||
|
def setLabelAngle(self, angle):
|
||||||
|
self.labelAngle = angle
|
||||||
|
self._updateLabel()
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
if self._picture is None:
|
||||||
|
self._drawPicture()
|
||||||
|
return self._bounds
|
||||||
|
|
||||||
|
def dataBounds(self, axis, frac=1.0, orthoRange=None):
|
||||||
|
return [0, 0]
|
||||||
|
|
||||||
|
def viewTransformChanged(self):
|
||||||
|
self._picture = None
|
||||||
|
self.prepareGeometryChange()
|
||||||
|
self._updateLabel()
|
||||||
|
|
||||||
|
def _updateLabel(self):
|
||||||
|
if self.label is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# find an optimal location for text at the given angle
|
||||||
|
angle = self.labelAngle * np.pi / 180.
|
||||||
|
lbr = self.label.boundingRect()
|
||||||
|
center = lbr.center()
|
||||||
|
a = abs(np.sin(angle) * lbr.height()*0.5)
|
||||||
|
b = abs(np.cos(angle) * lbr.width()*0.5)
|
||||||
|
r = max(self._radii) + 2 + max(a, b)
|
||||||
|
pos = self.mapFromScene(self.mapToScene(QtCore.QPointF(0, 0)) + r * QtCore.QPointF(np.cos(angle), -np.sin(angle)) - center)
|
||||||
|
self.label.setPos(pos)
|
||||||
|
|
||||||
|
def paint(self, p, *args):
|
||||||
|
if self._picture is None:
|
||||||
|
self._drawPicture()
|
||||||
|
self._picture.play(p)
|
||||||
|
|
||||||
|
def _drawPicture(self):
|
||||||
|
self._picture = QtGui.QPicture()
|
||||||
|
p = QtGui.QPainter(self._picture)
|
||||||
|
p.setRenderHint(p.Antialiasing)
|
||||||
|
|
||||||
|
# Note: could do this with self.pixelLength, but this is faster.
|
||||||
|
o = self.mapToScene(QtCore.QPointF(0, 0))
|
||||||
|
px = abs(1.0 / (self.mapToScene(QtCore.QPointF(1, 0)) - o).x())
|
||||||
|
py = abs(1.0 / (self.mapToScene(QtCore.QPointF(0, 1)) - o).y())
|
||||||
|
|
||||||
|
r, w, h = self._radii
|
||||||
|
w = w * px
|
||||||
|
h = h * py
|
||||||
|
rx = r * px
|
||||||
|
ry = r * py
|
||||||
|
rect = QtCore.QRectF(-rx, -ry, rx*2, ry*2)
|
||||||
|
p.setPen(self.pen)
|
||||||
|
p.setBrush(self.brush)
|
||||||
|
p.drawEllipse(rect)
|
||||||
|
p.drawLine(Point(-w, 0), Point(w, 0))
|
||||||
|
p.drawLine(Point(0, -h), Point(0, h))
|
||||||
|
p.end()
|
||||||
|
|
||||||
|
bx = max(w, rx)
|
||||||
|
by = max(h, ry)
|
||||||
|
self._bounds = QtCore.QRectF(-bx, -by, bx*2, by*2)
|
||||||
|
|
||||||
|
def mouseDragEvent(self, ev):
|
||||||
|
if not self.movable:
|
||||||
|
return
|
||||||
|
if ev.button() == QtCore.Qt.LeftButton:
|
||||||
|
if ev.isStart():
|
||||||
|
self.moving = True
|
||||||
|
self.cursorOffset = self.pos() - self.mapToParent(ev.buttonDownPos())
|
||||||
|
self.startPosition = self.pos()
|
||||||
|
ev.accept()
|
||||||
|
|
||||||
|
if not self.moving:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.setPos(self.cursorOffset + self.mapToParent(ev.pos()))
|
||||||
|
if ev.isFinish():
|
||||||
|
self.moving = False
|
||||||
|
self.sigDragged.emit(self)
|
||||||
|
|
||||||
|
def hoverEvent(self, ev):
|
||||||
|
if self.movable:
|
||||||
|
ev.acceptDrags(QtCore.Qt.LeftButton)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user