在PyQtGraph的官方例程中有此功能的实现,可参考Crosshair / Mouse interaction;但是坐标值的变化是超过整数时才变化,不符合实际开发中要求的精度。
在实现该功能的过程中主要参考了(详细分析)如何使用pyqt5和pyqtgraph在图像上增加图例并显示鼠标位置处的变量值,但是在获取鼠标所在位置的曲线的横纵坐标时使用了不同的方法,下面进行详细的介绍。
首先要创建曲线对象:
self.__m_temCurveLst = [0] * 10 # 温度曲线数组
self.__m_humCurveLst = [0] * 10 # 湿度曲线数组
self.ui.temCurve = self.ui.Curve.plot(self.__m_temCurveLst, pen=pg.mkPen('black', width=1), name="温度曲线")
self.ui.humCurve = self.ui.Curve.plot(self.__m_humCurveLst, pen=pg.mkPen('green', width=1), name="湿度曲线")
self.ui.Curve是图形对象PlotItem
如何基于GraphicsLayoutWidget创建曲线对象可以参考【Python_PyQtGraph 学习笔记】GraphicsLayoutWidget类的基本用法(持续更新)
之后的想法是:是否可以创建一个曲线上的点对象,然后获取鼠标的横坐标,根据鼠标的横坐标设置点对象的位置,这样曲线上的纵坐标就可以通过点对象的纵坐标而得到。
看文字可能不好理解,下面通过代码来进行展示。
创建坐标显示的标签:
self.ui.pwLabel = pg.LabelItem(justify='right') # 创建坐标的标签
self.ui.pw.addItem(self.ui.pwLabel) # 将坐标添加到GraphicsLayoutWidget布局中来
创建曲线对象上的点对象:
self.temPoint = pg.CurvePoint(self.ui.temCurve) # 创建温度曲线上的点
self.humPoint = pg.CurvePoint(self.ui.humCurve) # 创建湿度曲线上的点
又创建了一个箭头对象,可以更加清楚的看到点对象运动到了曲线对象的具体位置:
self.arrow = pg.ArrowItem(angle=90) # 创建一个箭头
self.arrow.setParentItem(self.ui.temPoint) # 将箭头添加到温度点上
这个箭头功能实现后,如果不想要可以注释掉,单纯的是为了更加直观的看到点的运动位置。
创建鼠标跟随的十字线:
self.vLine = pg.InfiniteLine(angle=90, movable=False) # 鼠标跟随的垂直方向的线
self.hLine = pg.InfiniteLine(angle=0, movable=False) # 鼠标跟随的水平方向的线
self.ui.Curve.addItem(self.vLine, ignoreBounds=True)
self.ui.Curve.addItem(self.hLine, ignoreBounds=True)
此功能也是属于可有可无的。
创建鼠标事件对象:
self.vb = self.ui.Curve.vb # 不含有坐标轴,但有鼠标功能的支持,获取鼠标事件,用户可以使用鼠标缩放/平移 ViewBox 的内容
self.proxy = pg.SignalProxy(self.ui.Curve.scene().sigMouseMoved, rateLimit=60, slot=self.__f_mouseMoved)
鼠标移动槽函数的实现:
# 私有方法: GraphicsLayoutWidget 鼠标移动响应函数
def __f_mouseMoved(self, evt):
"""
function:
in:
out:
return: int >0 ok, <0 somewrong
others:
"""
pos = evt[0] # 使用信号代理将原始参数转换为元组,获取事件的鼠标位置
mousePoint = self.vb.mapSceneToView(pos) # 鼠标所处的X轴坐标
if self.ui.Curve.sceneBoundingRect().contains(pos): # 如果鼠标位置在绘图部件中
if self.__m_curvePtr > 1: # 判断plot是否有大于一个点
self.temPoint.setPos(mousePoint.x() / (self.__m_curvePtr - 1)) # Point设置位置的float类型范围是0-1
self.humPoint.setPos(mousePoint.x() / (self.__m_curvePtr - 1)) # Point设置位置的float类型范围是0-1
self.ui.pwLabel.setText("时间:%0.2f\n"
"温度:%0.2f\n"
"湿度:%0.2f\n"
% (mousePoint.x(),
self.temPoint.pos().y(),
self.humPoint.pos().y()
))
# self.ui.pwLabel.setText("x:%0.2f\n"
# "y:%0.2f"
# % (mousePoint.x(), mousePoint.y()))
self.vLine.setPos(mousePoint.x()) # 设置垂直线的位置
self.hLine.setPos(mousePoint.y()) # 设置水平线的位置
self.__m_curvePtr: 曲线指针,曲线列表中每添加i一个数,指针+1
注意: 我们所获取的鼠标横坐标mousePoint.x()这个是大于1的,但是点对象的setPos()方法设置的参数是0~1范围内的。所以需要得到目前已经绘制的点的数量,也就是曲线的长度,两者相除即可得到点对象在曲线对象中的比例。这样就可以把点设置到鼠标所在位置的曲线上来,也就能得到鼠标所在位置曲线的纵坐标。
实现的效果图: