简体   繁体   English

具有多个断点的可拖动线

[英]draggable line with multiple break points

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 问题中提供的解决方案是一个很好的起点: 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: 我尝试通过修改__init__movable属性来使行可movable ,并添加一个setMovable方法,就像源代码中的源代码一样:

http://www.pyqtgraph.org/documentation/_modules/pyqtgraph/graphicsItems/InfiniteLine.html#InfiniteLine http://www.pyqtgraph.org/documentation/_modules/pyqtgraph/graphicsItems/InfiniteLine.html#InfiniteLine

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. 阈值点水平(TH_Px_L1)可拖动但不是时间(TH_Px_T1),因此点只能垂直移动。

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. 基于这个来自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. 散点图类型与绘制图形的图形类似,但是连接线位于i点点和它们连接的i + 1点点之间。 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_()

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM