I have a application very similar to the following question:Draw half infinite lines?
I would like to have a infinite line with multiple thresholds.
The solution provided in the question is a great starting point: https://stackoverflow.com/a/37836348/7163293
I attempted to make the lines movable by modifying the movable
attribute in __init__
and add a setMovable
method just as the source code in source:
from pyqtgraph.Qt import QtGui
import numpy as np
import pyqtgraph as pg
class InfiniteLineWithBreak(pg.GraphicsObject):
def __init__(self, changeX, levelsY, pen=None):
pg.GraphicsObject.__init__(self)
self.changeX = changeX
self.levelsY = levelsY
self.maxRange = [None, None]
self.moving = False
self.movable = True
self.setMovable(self.movable)
self.mouseHovering = False
pen = (200, 200, 100)
self.setPen(pen)
self.setHoverPen(color=(255,0,0), width=self.pen.width())
self.currentPen = self.pen
def setMovable(self, m):
"""Set whether the line is movable by the user."""
self.movable = m
self.setAcceptHoverEvents(m)
def setBounds(self, bounds):
self.maxRange = bounds
self.setValue(self.value())
def setPen(self, *args, **kwargs):
self.pen = pg.fn.mkPen(*args, **kwargs)
if not self.mouseHovering:
self.currentPen = self.pen
self.update()
def setHoverPen(self, *args, **kwargs):
self.hoverPen = pg.fn.mkPen(*args, **kwargs)
if self.mouseHovering:
self.currentPen = self.hoverPen
self.update()
def boundingRect(self):
br = self.viewRect()
return br.normalized()
def paint(self, p, *args):
br = self.boundingRect()
p.setPen(self.currentPen)
# three lines (left border to change point, change point vertical, change point to right)
p.drawLine(pg.Point(br.left(), self.levelsY[0]), pg.Point(self.changeX, self.levelsY[0]))
p.drawLine(pg.Point(self.changeX, self.levelsY[0]), pg.Point(self.changeX, self.levelsY[1]))
p.drawLine(pg.Point(self.changeX, self.levelsY[1]), pg.Point(br.right(), self.levelsY[1]))
def dataBounds(self, axis, frac=1.0, orthoRange=None):
if axis == 0:
return None ## x axis should never be auto-scaled
else:
return (0,0)
def setMouseHover(self, hover):
pass
app = QtGui.QApplication([])
w = pg.GraphicsWindow()
w.resize(1000, 600)
v = w.addPlot(y=np.random.normal(size=100))
v.addItem(InfiniteLineWithBreak(changeX=50, levelsY=(-1, 1)))
app.exec_()
However, the line is still not movable after the modifications.So I am kind of stuck here. Would someone be able to provide some pointers?
Also, ideally, the line on the applications should be movable by segments. So when the user drag a line, only the portion in between break points are moving. So ideally I would like to have something like:
Draggable line with draggable points
in my application. Ideally it would look something like
with the threshold point level (TH_Px_L1) draggable but not the timing (TH_Px_T1), so the points can only move vertically.
If someone can also help on the second item and provide some pointers or solution that will be very helpful.
Based on this example from docs.
A scatter type graph is similar to one where graphs are drawn, but where the connecting lines are between the i-point point and the i + 1-point point they are connected. Then we limit the movement only to the vertical axis since it is a requirement of the author.
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
pg.setConfigOptions(antialias=True)
w = pg.GraphicsWindow()
w.setWindowTitle('Draggable')
class Graph(pg.GraphItem):
def __init__(self):
self.dragPoint = None
self.dragOffset = None
pg.GraphItem.__init__(self)
def setData(self, **kwds):
self.data = kwds
if 'pos' in self.data:
npts = self.data['pos'].shape[0]
self.data['adj'] = np.column_stack((np.arange(0, npts-1), np.arange(1, npts)))
self.data['data'] = np.empty(npts, dtype=[('index', int)])
self.data['data']['index'] = np.arange(npts)
self.updateGraph()
def updateGraph(self):
pg.GraphItem.setData(self, **self.data)
def mouseDragEvent(self, ev):
if ev.button() != QtCore.Qt.LeftButton:
ev.ignore()
return
if ev.isStart():
pos = ev.buttonDownPos()
pts = self.scatter.pointsAt(pos)
if len(pts) == 0:
ev.ignore()
return
self.dragPoint = pts[0]
ind = pts[0].data()[0]
self.dragOffset = self.data['pos'][ind][1] - pos[1]
elif ev.isFinish():
self.dragPoint = None
return
else:
if self.dragPoint is None:
ev.ignore()
return
ind = self.dragPoint.data()[0]
self.data['pos'][ind][1] = ev.pos()[1] + self.dragOffset
self.updateGraph()
ev.accept()
g = Graph()
v = w.addPlot()
v.addItem(g)
x = np.linspace(1, 100, 40)
pos = np.column_stack((x, np.sin(x)))
g.setData(pos=pos, size=10, pxMode=True)
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()