You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQtGraph中点击背景取消曲线选中状态的实现方案咨询

PyQtGraph 点击图表背景取消曲线选中状态的实现方案

已实现PyQtGraph中点击曲线切换选中/取消选中的功能,现在需要补充点击图表背景时取消当前选中曲线的功能。此前尝试通过scene().sigMouseClicked事件获取点击元素,但存在两个问题:

  • 使用items()方法时,需大幅缩小图表才能识别背景点击;
  • 使用itemAt()方法时,会被十字线(InfiniteLine)遮挡,无法正确判断是否点击背景。

实现思路

通过监听场景的鼠标点击事件,遍历点击位置的所有元素:

  1. 排除坐标轴、十字线等辅助元素;
  2. 判断是否点击到曲线(PlotCurveItem);
  3. 若未点击到曲线且当前有选中曲线,则重置其样式并取消选中。

修改后的完整代码

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import Qt
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
        # 监听场景鼠标点击事件
        self.plot.scene().sigMouseClicked.connect(self.on_mouse_clicked)

    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实例,无需循环查找
        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:
                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)

    def on_mouse_clicked(self, event):
        # 仅处理左键点击
        if event.button() != Qt.LeftButton:
            return
        
        items = self.plot.scene().items(event.scenePos())
        clicked_on_curve = False
        
        for item in items:
            # 点击到曲线则标记
            if isinstance(item, pg.PlotCurveItem):
                clicked_on_curve = True
                break
            # 忽略十字线、坐标轴等辅助元素
            elif isinstance(item, (pg.InfiniteLine, pg.AxisItem, pg.ViewBox)):
                continue
        
        # 未点击曲线且有选中曲线时,取消选中
        if not clicked_on_curve and self.selected_curve is not None:
            self._reset_curve_properties(self.selected_curve)
            self.selected_curve = None


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('PyQtGraph Clickable Curves')
        self.graph_widget = GraphWidget()
        self.setCentralWidget(self.graph_widget)

        # 添加测试数据
        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_())

关键说明

  1. 事件监听:通过self.plot.scene().sigMouseClicked监听整个绘图场景的点击事件,确保能捕获背景点击;
  2. 元素过滤:遍历点击位置的元素时,排除InfiniteLine(十字线)、AxisItem(坐标轴)等辅助元素,只关注是否点击到PlotCurveItem;
  3. 选中状态重置:确认点击背景后,调用已有的_reset_curve_properties方法恢复曲线默认样式,并清空选中标记。

内容的提问来源于stack exchange,提问作者Souleater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 11:50:07