Hover Tool for plots in Pyqtgraph
Question:
I want to have data information shown when hovering over a line in pyqtgraph plots, but can’t get my sigpointsHovered
to emit any signal. Here is a simple example of what i tried to do:
from PySide6.QtWidgets import QMainWindow, QWidget, QApplication, QVBoxLayout
import pyqtgraph as pg
def hovered(self, points, ev):
print("FOOO")
x = [1,2,3,4,5,6,7,8,9]
y = [0,1,2,3,4,5,6,7,8]
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
plot_widget = pg.PlotWidget()
plot_item = plot_widget.getPlotItem()
line = plot_item.plot(x,y)
line.sigPointsHovered.connect(hovered)
layout.addWidget(plot_widget)
window.setLayout(layout)
window.show()
app.exec_()
I have already tried setting "hoverable" = True
and read the docs several times, but I honestly have no clue why the sigPointsHovered
is not working.
Answers:
Why sigPointsHovered
is not working
In short: There is no way to set "hoverable" argument for PlotDataItem
class’s ScatterPlotItem
right now. Therefore, it is not possible to use sigPointsHovered
.
You could see this in the source code of PlotDataItem
class’s function updateItems
.
Workarounds
-
If you really want something like sigPointsHovered
right now, instead of using a PlotWiget
, use a ScatterPlotItem
and set hoverable = True
when you initialize it or when you use setData
function. Run python -m pyqtgraph.examples
and find the scatter plot example to see some example codes.
-
However, from your description, I think you actually want to do something when you hover over a "cruve" (instead of points). Currently, PlotCurveItem
doesn’t implement a hoverEvent
, so you may try to make a class that inherits the PlotCurveItem
and add a hoverEvent
to it.
Let me show you how to do this.
In this example, when the cursor enters the curve, the color changes to blue, and turn back to white when it leave the curve.
import pyqtgraph as pg
from pyqtgraph import QtCore, QtGui
class HoverableCurveItem(pg.PlotCurveItem):
sigCurveHovered = QtCore.Signal(object, object)
sigCurveNotHovered = QtCore.Signal(object, object)
def __init__(self, hoverable=True, *args, **kwargs):
super(HoverableCurveItem, self).__init__(*args, **kwargs)
self.hoverable = hoverable
self.setAcceptHoverEvents(True)
def hoverEvent(self, ev):
if self.hoverable:
if self.mouseShape().contains(ev.pos()):
self.sigCurveHovered.emit(self, ev)
else:
self.sigCurveNotHovered.emit(self, ev)
class MainWindow(QtGui.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.view = pg.GraphicsLayoutWidget()
self.setCentralWidget(self.view)
self.makeplot()
def makeplot(self):
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
y = [0, 1, 2, 3, 4, 5, 6, 7, 8]
plot = self.view.addPlot()
self.plotitem = HoverableCurveItem(x, y, pen=pg.mkPen('w', width=10))
self.plotitem.setClickable(True, width=10)
self.plotitem.sigCurveHovered.connect(self.hovered)
self.plotitem.sigCurveNotHovered.connect(self.leaveHovered)
plot.addItem(self.plotitem)
def hovered(self):
print("cursor entered curve")
self.plotitem.setPen(pg.mkPen('b', width=10))
def leaveHovered(self):
self.plotitem.setPen(pg.mkPen('w', width=10))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())
Edit
Need to setAcceptHoverEvent
to Ture
Also, in the updated example, when the cursor enters the curve, the color changes to blue, and turn back to white when it leave the curve.
Also, does anyone know of a solution to apply the hover event to individual data points as well?
I would like to hover my mouse over a data point and have information about that point displayed (without clicking on it).
I want to have data information shown when hovering over a line in pyqtgraph plots, but can’t get my sigpointsHovered
to emit any signal. Here is a simple example of what i tried to do:
from PySide6.QtWidgets import QMainWindow, QWidget, QApplication, QVBoxLayout
import pyqtgraph as pg
def hovered(self, points, ev):
print("FOOO")
x = [1,2,3,4,5,6,7,8,9]
y = [0,1,2,3,4,5,6,7,8]
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
plot_widget = pg.PlotWidget()
plot_item = plot_widget.getPlotItem()
line = plot_item.plot(x,y)
line.sigPointsHovered.connect(hovered)
layout.addWidget(plot_widget)
window.setLayout(layout)
window.show()
app.exec_()
I have already tried setting "hoverable" = True
and read the docs several times, but I honestly have no clue why the sigPointsHovered
is not working.
Why sigPointsHovered
is not working
In short: There is no way to set "hoverable" argument for PlotDataItem
class’s ScatterPlotItem
right now. Therefore, it is not possible to use sigPointsHovered
.
You could see this in the source code of PlotDataItem
class’s function updateItems
.
Workarounds
-
If you really want something like
sigPointsHovered
right now, instead of using aPlotWiget
, use aScatterPlotItem
and sethoverable = True
when you initialize it or when you usesetData
function. Runpython -m pyqtgraph.examples
and find the scatter plot example to see some example codes. -
However, from your description, I think you actually want to do something when you hover over a "cruve" (instead of points). Currently,
PlotCurveItem
doesn’t implement ahoverEvent
, so you may try to make a class that inherits thePlotCurveItem
and add ahoverEvent
to it.
Let me show you how to do this.
In this example, when the cursor enters the curve, the color changes to blue, and turn back to white when it leave the curve.
import pyqtgraph as pg
from pyqtgraph import QtCore, QtGui
class HoverableCurveItem(pg.PlotCurveItem):
sigCurveHovered = QtCore.Signal(object, object)
sigCurveNotHovered = QtCore.Signal(object, object)
def __init__(self, hoverable=True, *args, **kwargs):
super(HoverableCurveItem, self).__init__(*args, **kwargs)
self.hoverable = hoverable
self.setAcceptHoverEvents(True)
def hoverEvent(self, ev):
if self.hoverable:
if self.mouseShape().contains(ev.pos()):
self.sigCurveHovered.emit(self, ev)
else:
self.sigCurveNotHovered.emit(self, ev)
class MainWindow(QtGui.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.view = pg.GraphicsLayoutWidget()
self.setCentralWidget(self.view)
self.makeplot()
def makeplot(self):
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
y = [0, 1, 2, 3, 4, 5, 6, 7, 8]
plot = self.view.addPlot()
self.plotitem = HoverableCurveItem(x, y, pen=pg.mkPen('w', width=10))
self.plotitem.setClickable(True, width=10)
self.plotitem.sigCurveHovered.connect(self.hovered)
self.plotitem.sigCurveNotHovered.connect(self.leaveHovered)
plot.addItem(self.plotitem)
def hovered(self):
print("cursor entered curve")
self.plotitem.setPen(pg.mkPen('b', width=10))
def leaveHovered(self):
self.plotitem.setPen(pg.mkPen('w', width=10))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())
Edit
Need to setAcceptHoverEvent
to Ture
Also, in the updated example, when the cursor enters the curve, the color changes to blue, and turn back to white when it leave the curve.
Also, does anyone know of a solution to apply the hover event to individual data points as well?
I would like to hover my mouse over a data point and have information about that point displayed (without clicking on it).