I try to deselect a curve by clicking on the background in a pyqtgraph. So when I click on a curve, it is selecting it and when I click on the background or the curve again, it should deselect it. If there is no curve selected at the moment and I click on the background, it should do nothing.
Clicking and selecting/deselecting a curve by clicking the curve is working perfectly fine, here a small example:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
import pyqtgraph as pg
class GraphWidget(pg.GraphicsLayoutWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.plot = self.addPlot()
self.curves = []
self.selected_curve = None
def add_curve(self, x, y, pen):
curve = self.plot.plot(x, y, pen=pen)
curve.setCurveClickable(True)
curve.sigClicked.connect(self.curve_click)
self.curves.append(curve)
def curve_click(self, curve):
curve_inst = None
# Get curve instance
for line_item in self.curves:
if line_item == curve:
curve_inst = line_item
if curve == self.selected_curve:
self._reset_curve_properties(curve)
self.selected_curve = None
return
for line_item in self.curves:
pen = line_item.opts['pen']
pen = pg.mkPen(pen)
if line_item == curve_inst:
selected_pen = pg.mkPen(color=pen.color(), width=2)
line_item.setPen(selected_pen)
self.selected_curve = line_item
else:
default_pen = pg.mkPen(color=pen.color(), width=1)
line_item.setPen(default_pen)
def _reset_curve_properties(self, curve):
pen = curve.opts['pen']
default_pen = pg.mkPen(color=pen.color(), width=1)
curve.setPen(default_pen)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('PyQtGraph Clickable Curves')
self.graph_widget = GraphWidget()
self.setCentralWidget(self.graph_widget)
# Add some test data
x = list(range(10))
y1 = [i for i in x]
y2 = [i ** 2 for i in x]
self.graph_widget.add_curve(x, y1, pen='r')
self.graph_widget.add_curve(x, y2, pen='b')
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
Now I just need to accomplish that it is also deselecting it when clicking the background.
I connected the mouse click:
self.plot.scene().sigMouseClicked.connect(self.on_mouse_clicked)
Then in on_mouse_clicked getting the items at clicked position:
items = self.plot_widget.scene().items(event.scenePos())
But this only gives me all items in the viewBox (or in a certain range where I clicked). I checked if there are no PlotCurveItems in the returned list; if there is no curve in this list, then it should deselect, because this means that I clicked on the background.
This doesn't work properly though, I have to zoom out a lot and click somewhere further away such that it doesn't recognize any curve anymore.
Also with .itemAt() it isn't working. In my original program I have a crosshair cursor with a horizontal and vertical DashLine, so this is what I get in return (.InfiniteLine), as this is the top most item.
Is it possible at all to recognize the background click?
You can use event.isAccepted()
to check if the mouse position was on a plot item, like the following.
...
class GraphWidget(pg.GraphicsLayoutWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.plot = self.addPlot()
self.curves = []
self.selected_curve = None
def on_click_scene(event):
if not event.isAccepted():
if self.selected_curve:
self._reset_curve_properties(self.selected_curve)
self.selected_curve = None
self.scene().sigMouseClicked.connect(on_click_scene)
...