Q&A: How to show a custom cursor on a PyQtGraph plot?
Changing the OS cursor and implementing a custom crosshair

When working with plots changing the cursor can help with pointing accuracy. For example, if you need to isolate particular points in a scatter plot a cross-hair will give you a more accurate view of where you are pointing than the standard arrow cursor.

Changing the mouse cursor

Changing the mouse cursor in a PyQtGraph is fairly simple and uses Qt's built-in support for custom cursors over a widget. Since the PyQtGraph PlotWidget is a subclass of QGraphicsWidget (and therefore QWidget) you can use the standard methods.

python
    cursor = Qt.CrossCursor
    self.graphWidget.setCursor(cursor)

For the complete list of cursor types, see the Qt documentation. The example below shows this in action on a simple PyQtGraph plot.

python
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow, QApplication
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys  # We need sys so that we can pass argv to QApplication
import os

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.graphWidget = pg.PlotWidget()
        self.setCentralWidget(self.graphWidget)

        hour = [1,2,3,4,5,6,7,8,9,10]
        temperature = [30,32,34,32,33,31,29,32,35,45]

        #Add Background colour to white
        self.graphWidget.setBackground('w')
        # Add Title
        self.graphWidget.setTitle("Your Title Here", color="b", size="30pt")
        # Add Axis Labels
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        #Add legend
        self.graphWidget.addLegend()
        #Add grid
        self.graphWidget.showGrid(x=True, y=True)
        #Set Range
        self.graphWidget.setXRange(0, 10, padding=0)
        self.graphWidget.setYRange(20, 55, padding=0)

        pen = pg.mkPen(color=(255, 0, 0))

        self.graphWidget.plot(hour, temperature, name="Sensor 1",  pen=pen, symbol='+', symbolSize=30, symbolBrush=('b'))

        # Set the cursor for the plotwidget. The mouse cursor will change when over the plot.
        cursor = Qt.CrossCursor
        self.graphWidget.setCursor(cursor)


app = QApplication(sys.argv)
main = MainWindow()
main.show()
app.exec_()

If you run this you'll see a cross-hair cursor appear when you hover your mouse over the plot.

Mouse cursor as crosshair Crosshair cursor on plot

Drawing a custom cursor

If you want to show a completely custom cursor, for example an full-size crosshair over the plot, things are a little trickier. In this case you need to draw the cursor yourself by adding elements to the plot and then listening for mouse events and updating their position.

The code below is an updated version of the plot above, with two crosshair lines added using PyQtGraphs InfiniteLine objects. The lines are drawn in the __init__ method, and then updated in the mouseMoved method.

You could also add any other QGraphicsScene item here instead.

The important part is the SignalProxy which forwards mouse movements to our custom method update_crosshair. The rateLimit parameter sets the maximum number of signals per second which will be sent, to avoid overloading our handler/app with excessive events.

python
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import Qt
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys  # We need sys so that we can pass argv to QApplication
import os


class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.graphWidget = pg.PlotWidget()
        self.setCentralWidget(self.graphWidget)

        hour = [1,2,3,4,5,6,7,8,9,10]
        temperature = [30,32,34,32,33,31,29,32,35,45]

        #Add Background colour to white
        self.graphWidget.setBackground('w')
        # Add Title
        self.graphWidget.setTitle("Your Title Here", color="b", size="30pt")
        # Add Axis Labels
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        #Add legend
        self.graphWidget.addLegend()
        #Add grid
        self.graphWidget.showGrid(x=True, y=True)
        #Set Range
        self.graphWidget.setXRange(0, 10, padding=0)
        self.graphWidget.setYRange(20, 55, padding=0)

        pen = pg.mkPen(color=(255, 0, 0))
        self.graphWidget.plot(hour, temperature, name="Sensor 1",  pen=pen, symbol='+', symbolSize=30, symbolBrush=('b'))

        # Add crosshair lines.
        self.crosshair_v = pg.InfiniteLine(angle=90, movable=False)
        self.crosshair_h = pg.InfiniteLine(angle=0, movable=False)
        self.graphWidget.addItem(self.crosshair_v, ignoreBounds=True)
        self.graphWidget.addItem(self.crosshair_h, ignoreBounds=True)

        self.proxy = pg.SignalProxy(self.graphWidget.scene().sigMouseMoved, rateLimit=60, slot=self.update_crosshair)

    def update_crosshair(self, e):
        pos = e[0]
        if self.graphWidget.sceneBoundingRect().contains(pos):
            mousePoint = self.graphWidget.getPlotItem().vb.mapSceneToView(pos)
            self.crosshair_v.setPos(mousePoint.x())
            self.crosshair_h.setPos(mousePoint.y())


app = QApplication(sys.argv)
main = MainWindow()
main.show()
app.exec_()


If you run this example, in addition to the mouse cursor you'll also see a faint yellow line overlaying the plot.

Drawing the custom cursor lines The custom cursor with default mouse cursor hidden

To hide the default mouse cursor over the plot set the curser type to Qt.BlankCursor. For example.

python
class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        # ... rest of __init__ as before

        # Hide the cursor over the plot.
        cursor = Qt.BlankCursor
        self.graphWidget.setCursor(cursor)

This will give the following result when hovering over the plot.

Drawing the custom cursor lines The custom cursor with default mouse cursor hidden

Continue reading

Plotting with PyQtGraph  pyside

One of the major strengths of Python is in exploratory data science and visualization, using tools such as Pandas, numpy, sklearn for data analysis and matplotlib plotting. Buiding GUI applications with PySide gives you access to all these Python tools directly from within your app, allowing you to build complex … More