Как переместить ось X пиктографа назад и четвертым, когда перетаскиваемая линия приближается к окончанию X-диапазона? - PullRequest
1 голос
/ 15 апреля 2020

У меня есть график-виджет pyqtgraph, отображающий кривую, и я показываю только ограниченный диапазон оси X из-за большого массива данных. Я хотел бы использовать перетаскиваемую линию, чтобы pu sh ось X повернулась назад и четвертой, когда линия перетаскивается рядом и проходит через окончания X-диапазона.

Это я и сделал. Однако, когда в полноэкранном режиме событие перетаскивания перестает обновляться, когда мышь не может двигаться дальше вправо или влево от экрана.

Как я могу продолжить обновление оси X, даже если мышь находится в положении c, но около концов диапазона X?

Пример кода:

# Import packages
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout
import numpy as np
import sys
import pyqtgraph as pg

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.verticalLayout = QVBoxLayout(self)

        # Add graph plot
        self.graph = pg.PlotWidget()
        self.verticalLayout.addWidget(self.graph)

        # Set view range to 200 as default
        self.startX = 0
        self.endX = 200

        self.graph.setMouseEnabled(x=False, y=False)  # disable mouse events in graph
        self.graph.hideButtons()
        self.graph.setXRange(self.startX, self.endX, padding=0) # Set view range to 200 as default
        self.curve = self.graph.plot(pen="w") # Add line to plot

        data = np.random.random(size=10000)

        self.curve.setData(data)

        # Add line to graph plot
        self.vLine = pg.InfiniteLine(movable=True, angle=90, pen=[75, 82, 159, 200])
        self.graph.addItem(self.vLine)
        self.vLine.setPos(100)
        self.graph.scene().sigMouseClicked.connect(self.moveLine)
        self.vLine.sigDragged.connect(self.pushLine)

        self.setLayout(self.verticalLayout)

    def pushLine(self):
        pos = self.vLine.getPos()
        axX = self.graph.getAxis('bottom')

        while pos[0] <= axX.range[0]:
            self.graph.setXRange(axX.range[0]-1, axX.range[1]-1, padding=0)

        while pos[0] >= axX.range[1]:
            self.graph.setXRange(axX.range[0]+1, axX.range[1]+1, padding=0)

    def moveLine(self, mouse_event):
        vb = self.graph.getViewBox()
        view_coords = vb.mapSceneToView(mouse_event.scenePos())
        view_x = view_coords.x()
        self.vLine.setPos(view_x)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

1 Ответ

1 голос
/ 15 апреля 2020

Я понял это. Мне пришлось добавить QTimer, который будет запускаться, когда я перетаскиваю линию, и снова останавливаться при отпускании. Это создавало постоянно обновляемый сигнал при перетаскивании. См. Ниже, чтобы найти код:

# Import packages
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout
from PyQt5.QtCore import QTimer
import numpy as np
import sys
import pyqtgraph as pg

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.verticalLayout = QVBoxLayout(self)

        # Add graph plot
        self.graph = pg.PlotWidget()
        self.verticalLayout.addWidget(self.graph)

        # Set view range to 200 as default
        self.startX = 0
        self.endX = 200

        self.graph.setMouseEnabled(x=False, y=False)  # disable mouse events in graph
        self.graph.hideButtons()
        self.graph.setXRange(self.startX, self.endX, padding=0) # Set view range to 200 as default
        self.curve = self.graph.plot(pen="w") # Add line to plot

        data = np.random.random(size=10000)

        self.curve.setData(data)

        # Add line to graph plot
        self.vLine = pg.InfiniteLine(movable=True, angle=90, pen=[75, 82, 159, 200])
        self.graph.addItem(self.vLine)
        self.vLine.setPos(100)
        self.graph.scene().sigMouseClicked.connect(self.moveLine)

        self.setLayout(self.verticalLayout)

        self.playTimer = QTimer()
        self.proxy = pg.SignalProxy(self.graph.scene().sigMouseMoved, rateLimit=30, slot=self.OnMouseMove)
        self.graph.scene().sigMouseClicked.connect(self.release)
        self.playTimer.timeout.connect(self.release)

    def release(self):
        pos = self.vLine.getPos()
        axX = self.graph.getAxis('bottom')

        if pos[0] <= axX.range[0]:
            self.graph.setXRange(axX.range[0]-1, axX.range[1]-1, padding=0)
            self.vLine.setPos(axX.range[0])

        if pos[0] >= axX.range[1]:
            self.graph.setXRange(axX.range[0]+1, axX.range[1]+1, padding=0)
            self.vLine.setPos(axX.range[1])

        if not self.graph.scene().clickEvents:  # Drag function
            self.playTimer.stop()

    def OnMouseMove(self):
        if not self.playTimer.isActive() and self.graph.scene().clickEvents:
            self.playTimer.start(10)  # After a drag release, this is the "wait" time before self.release is called.

    def moveLine(self, mouse_event):
        vb = self.graph.getViewBox()
        view_coords = vb.mapSceneToView(mouse_event.scenePos())
        view_x = view_coords.x()
        self.vLine.setPos(view_x)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())
...