I have a pyqtgraph plotwidget displaying a curve and I am only showing a limited range of the X-axis due to the large data array. I would like to use a draggable line to push the X-axis back and fourth when the line is dragged near and pass the endings of the X-range.
This I have done. However, when in full screen the drag event stops updating when the mouse cant move further to the right or left of the screen.
How can I continue updating the X-Axis even when the mouse is static but near the endings of the X-Range?
Sample code:
# 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_())
I figured it out. I had to add a QTimer that would start when i dragged the line and stop again when releasing. This created a continously updating signal while dragging. See below to find the code:
# 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_())