Hey guys,
i'm trying to modify the InfLineLabel class so that its x-position is fixed
and its y-position is relative to the viewbox, just like when a normal
InflineLabel is attached to a vertical InfiniteLine. If it's parent isn't a
InfLine, it behaves like it's attached to a horizontal one, meaning it's
locked to the y-position instead to the x and it can be moved along the
x-axis instead of the y. I simply cannot find at all where or how the
alignment of the line is checked.
The changes are really rudimentary, but i attached the modified class. I'd
really appreciate if someone could help me out.
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/83f95d5c-56c1-4ba8-baf1-8cbf194982aan%40googlegroups.com.
from PyQt5 import QtGui, QtCore
from pyqtgraph.Point import Point
from pyqtgraph.graphicsItems.TextItem import TextItem
from pyqtgraph.graphicsItems.ViewBox import ViewBox
from pyqtgraph import functions as fn
import numpy as np
import weakref
import time
class MyInfLineLabel(TextItem):
"""
A TextItem that attaches itself to an InfiniteLine.
This class extends TextItem with the following features:
* Automatically positions adjacent to the line at a fixed position along
the line and within the view box.
* Automatically reformats text when the line value has changed.
* Can optionally be dragged to change its location along the line.
* Optionally aligns to its parent line.
===============
==================================================================
**Arguments:**
line The InfiniteLine to which this label will be attached.
text String to display in the label. May contain a {value}
formatting
string to display the current value of the line.
movable Bool; if True, then the label can be dragged along the line.
position Relative position (0.0-1.0) within the view to position the
label
along the line.
anchors List of (x,y) pairs giving the text anchor positions that
should
be used when the line is moved to one side of the view or
the
other. This allows text to switch to the opposite side of
the line
as it approaches the edge of the view. These are
automatically
selected for some common cases, but may be specified if the
default values give unexpected results.
===============
==================================================================
All extra keyword arguments are passed to TextItem. A particularly useful
option here is to use `rotateAxis=(1, 0)`, which will cause the text to
be automatically rotated parallel to the line.
"""
def __init__(self, line, value, text="", movable=False, position=0.5,
anchors=None, **kwds):
self.line = line
self.value = value
self.movable = movable
self.moving = False
self.orthoPos = position # text will always be placed on the line at a
position relative to view bounds
self.format = text
self._endpoints = (None, None)
if anchors is None:
anchors = [(0, 0.5), (1, 0.5)]
self.anchors = anchors
TextItem.__init__(self, **kwds)
self.setParentItem(line)
self.valueChanged()
def valueChanged(self):
if not self.isVisible():
return
value = self.value
self.setText(self.format.format(value=value))
self.updatePosition()
def getEndpoints(self):
# calculate points where line intersects view box
# (in line coordinates)
if self._endpoints[0] is None:
lr = self.line.boundingRect()
pt1 = Point(lr.left(), 0)
pt2 = Point(lr.right(), 0)
self._endpoints = (pt1, pt2)
return self._endpoints
def updatePosition(self):
# update text position to relative view location along line
self._endpoints = (None, None)
pt1, pt2 = self.getEndpoints()
if pt1 is None:
return
pt = pt2 * self.orthoPos + pt1 * (1 - self.orthoPos)
self.setPos(pt)
# update anchor to keep text visible as it nears the view box edge
vr = self.line.viewRect()
if vr is not None:
self.setAnchor(self.anchors[0 if vr.center().y() < 0 else 1])
def setVisible(self, v):
TextItem.setVisible(self, v)
if v:
self.updateText()
self.updatePosition()
def setMovable(self, m):
"""Set whether this label is movable by dragging along the line.
"""
self.movable = m
self.setAcceptHoverEvents(m)
def setPosition(self, p):
"""Set the relative position (0.0-1.0) of this label within the view box
and along the line.
For horizontal (angle=0) and vertical (angle=90) lines, a value of 0.0
places the text at the bottom or left of the view, respectively.
"""
self.orthoPos = p
self.updatePosition()
def setFormat(self, text):
"""Set the text format string for this label.
May optionally contain "{value}" to include the lines current value
(the text will be reformatted whenever the line is moved).
"""
self.format = text
self.valueChanged()
def mouseDragEvent(self, ev):
if self.movable and ev.button() == QtCore.Qt.LeftButton:
if ev.isStart():
self._moving = True
self._cursorOffset = self._posToRel(ev.buttonDownPos())
self._startPosition = self.orthoPos
ev.accept()
if not self._moving:
return
rel = self._posToRel(ev.pos())
self.orthoPos = np.clip(self._startPosition + rel -
self._cursorOffset, 0, 1)
self.updatePosition()
if ev.isFinish():
self._moving = False
def mouseClickEvent(self, ev):
if self.moving and ev.button() == QtCore.Qt.RightButton:
ev.accept()
self.orthoPos = self._startPosition
self.moving = False
def hoverEvent(self, ev):
if not ev.isExit() and self.movable:
ev.acceptDrags(QtCore.Qt.LeftButton)
def viewTransformChanged(self):
self.updatePosition()
TextItem.viewTransformChanged(self)
def _posToRel(self, pos):
# convert local position to relative position along line between view
bounds
pt1, pt2 = self.getEndpoints()
if pt1 is None:
return 0
view = self.getViewBox()
pos = self.mapToParent(pos)
return (pos.x() - pt1.x()) / (pt2.x() - pt1.x())