如何将鼠标点击信号连接到 pyqtgraph 绘图小部件

Posted

技术标签:

【中文标题】如何将鼠标点击信号连接到 pyqtgraph 绘图小部件【英文标题】:How to connect mouse clicked signal to pyqtgraph plot widget 【发布时间】:2020-02-19 22:40:06 【问题描述】:

我有 Qt 应用程序,我在其中使用 pyqtgraph lib 绘制图形,并使用来自 pyqtgraph 的停靠容器。所以我创建了几个停靠容器并在每个容器中放置一个图表。然后,在我的代码中,我需要识别用户正在使用的图表来更新应用程序中的其他一些员工(例如,在所有小部件的一些通用中显示“活动”图表的一些属性)。

我的想法是接收鼠标点击信号并识别点击它的图表以了解最后一个图表用户交互。但是 pyqtgraph PlotWidget、PlotItem 或 ViewBox 类不提供这样的信号,我不知道是否有办法自己实现它。此外,我没有找到一种方法来识别哪个码头容器处于活动状态。 我只看到 PlotWidget 的 sigMouseReleased 但即使这对我也不起作用(参见下面的代码)

这是我的最低代码:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import pyqtgraph as pg
from pyqtgraph.dockarea import *

# I use Qt Designer, below I just cut generated code to minimum
class Ui_StartForm(object):
    def setupUi(self, StartForm):
        StartForm.setObjectName("StartForm")
        StartForm.resize(1507, 968)
        self.GraphLayout = QtWidgets.QGridLayout(StartForm)

# my application
class AppWindow(QtWidgets.QWidget, Ui_StartForm):
    def __init__(self):
        super(AppWindow, self).__init__()
        self.setupUi(self)

        self.dock_area_main = DockArea()
        self.GraphLayout.addWidget(self.dock_area_main)

        self.Dock1 = Dock("Dock 1", size=(1, 1))
        self.dock_area_main.addDock(self.Dock1, 'left')

        self.Dock2 = Dock("Dock 2", size=(1, 1))
        self.dock_area_main.addDock(self.Dock2, 'right')

        self.GraphViewList = []

        self.pl1 = pg.PlotWidget()
        self.pl2 = pg.PlotWidget()

        self.Dock1.addWidget(self.pl1)
        self.Dock2.addWidget(self.pl2)

        self.pl1.sigMouseReleased.connect(self.mouse_release) # try to get some mouse event

    def mouse_release(self):
        print('click')   # never execute


app = QtWidgets.QApplication(sys.argv)
w = AppWindow()
w.show()
sys.exit(app.exec_())

我的问题是如何为 pyqtgraph PlotItem 或 ViewBox 实现信号鼠标单击,以识别用户上次交互的图形。同时,它不应该影响pyqtgraph绘图的功能(它应该正常捕获所有鼠标事件)

如果有更好的策略 - 请提出建议

【问题讨论】:

【参考方案1】:

PyQtGraph 确实GraphicsScene 类中实现了一个 sigMouseClicked 信号,但不知何故,这是未记录的。 GraphicsScene page 仅解释了为什么它实现了并行鼠标事件系统,但如果您查看 the source 您会发现它也发出一些方便的信号。

由于这些没有记录,您应该自担风险使用它们!也许它们将来会改变,尽管我认为这不太可能。或者,也许您可​​以打开一个问题并要求他们得到官方支持。

信号将原始鼠标事件作为参数。没有对单击的绘图的引用,但是如果您可以通过覆盖 pg.PlotWidget 并连接到该派生类的插槽来解决此问题。就这样……

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import pyqtgraph as pg
from pyqtgraph.dockarea import *

# I use Qt Designer, below I just cut generated code to minimum
class Ui_StartForm(object):
    def setupUi(self, StartForm):
        StartForm.setObjectName("StartForm")
        StartForm.resize(1507, 968)
        self.GraphLayout = QtWidgets.QGridLayout(StartForm)


class MyPlotWidget(pg.PlotWidget):

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

        # self.scene() is a pyqtgraph.GraphicsScene.GraphicsScene.GraphicsScene
        self.scene().sigMouseClicked.connect(self.mouse_clicked)    


    def mouse_clicked(self, mouseClickEvent):
        # mouseClickEvent is a pyqtgraph.GraphicsScene.mouseEvents.MouseClickEvent
        print('clicked plot 0x:x, event: '.format(id(self), mouseClickEvent))



# my application
class AppWindow(QtWidgets.QWidget, Ui_StartForm):
    def __init__(self):
        super(AppWindow, self).__init__()
        self.setupUi(self)

        self.dock_area_main = DockArea()
        self.GraphLayout.addWidget(self.dock_area_main)

        # Best to use lower case for variables and upper case for types, so I
        # renamed self.Dock1 to self.dock1.        

        self.dock1 = Dock("Dock 1", size=(1, 1)) 
        self.dock_area_main.addDock(self.dock1, 'left')

        self.dock2 = Dock("Dock 2", size=(1, 1))
        self.dock_area_main.addDock(self.dock2, 'right')

        self.GraphViewList = []

        self.pl1 = MyPlotWidget()
        self.pl2 = MyPlotWidget()

        self.dock1.addWidget(self.pl1)
        self.dock2.addWidget(self.pl2)



app = QtWidgets.QApplication(sys.argv)
w = AppWindow()
w.show()
sys.exit(app.exec_())

【讨论】:

嗨titusjan,非常感谢您的回答,您的示例效果很好。再问一个问题。我的原始代码可以识别鼠标单击绘制的曲线,以便我可以在某处显示该曲线的属性并编辑设置。代码在绘图上绘制曲线:curve = pl.plot(y, pen='b'),然后连接到鼠标单击:curve.sigClicked.connect(self.sig_update_conf)。在我用您提供的解决方案修改我的代码后,上述功能不再起作用。据我了解,我拦截了鼠标点击,它不会去绘图对象。有没有办法同时举办这两个活动? 你必须让你的曲线可点击。所以curve.curve.setClickable(True).

以上是关于如何将鼠标点击信号连接到 pyqtgraph 绘图小部件的主要内容,如果未能解决你的问题,请参考以下文章

Pyqtgraph 中绘图的悬停工具

如何在pyqtgraph中绘制十字准线并绘制鼠标位置?

pyqtgraph绘图如何使用pyqtgraph

pyqtgraph 轴未正确显示

pyqtgraph 绘图小部件未更新

如何将信号连接到插槽