How to show a custom cursor on a PyQtGraph plot?

Changing the OS cursor and implementing a custom crosshair
Heads up! You've already completed this tutorial.

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

In this tutorial, you'll learn two approaches to adding a custom cursor to a PyQtGraph plot: using Qt's built-in cursor shapes and drawing a fully custom crosshair overlay using PyQtGraph's InfiniteLine.

Changing the Mouse Cursor on a PyQtGraph PlotWidget

Changing the mouse cursor in a PyQtGraph plot 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 Qt cursor 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().__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 crosshair cursor appear when you hover your mouse over the plot.

Mouse cursor as crosshair on a PyQtGraph plot Crosshair cursor on a PyQtGraph PlotWidget

Drawing a Custom Crosshair Cursor with InfiniteLine

If you want to show a completely custom cursor — for example, a full-size crosshair overlay spanning the entire 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 to update their position.

The code below is an updated version of the plot above, with two crosshair lines added using PyQtGraph's InfiniteLine objects. The lines are created in the __init__ method and then updated in the update_crosshair method whenever the mouse moves.

You could also add any other QGraphicsScene item here instead.

The important part is the SignalProxy which forwards mouse movement signals to our custom update_crosshair method. 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().__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 custom crosshair cursor lines on a PyQtGraph plot Custom crosshair overlay with the default mouse cursor still visible

Hiding the Default Mouse Cursor Over the Plot

To hide the default mouse cursor over the plot, set the cursor type to Qt.BlankCursor. This gives you a clean crosshair-only cursor experience, which is useful for precise data point selection in PyQtGraph.

python
class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super().__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.

Custom crosshair cursor with default mouse cursor hidden on PyQtGraph plot The custom crosshair cursor with the default mouse cursor hidden

Summary

In this tutorial you learned two ways to customize the mouse cursor on a PyQtGraph PlotWidget in PyQt5:

  1. Built-in Qt cursors — Use setCursor() with cursor types like Qt.CrossCursor for a quick solution.
  2. Custom crosshair overlay — Use PyQtGraph's InfiniteLine combined with SignalProxy and sigMouseMoved to draw full-size crosshair lines that track the mouse position across the plot.
  3. Hiding the default cursor — Set Qt.BlankCursor to remove the OS cursor and show only your custom crosshair.

These techniques work with any PyQtGraph plot type, including scatter plots, line charts, and real-time data visualizations, making them ideal for building interactive Python GUI applications with PyQt5.

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Create GUI Applications with Python & Qt5 by Martin Fitzpatrick

(PyQt5 Edition) The hands-on guide to making apps with Python — Over 15,000 copies sold!

More info Get the book

Martin Fitzpatrick

How to show a custom cursor on a PyQtGraph plot? was written by Martin Fitzpatrick.

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular Python books on the subject.