PyQt5记录笔记之使用Matplotlib绘图

@PyQt5记录笔记之使用Matplotlib绘图

PyQt5上创建Matplotlib绘图的基本流程

1,要在PyQt5界面上显示,首先要创建界面组件FigureCanvas,一个画布(相当于用于显示Matplotlib的Widget组件);
2,接着需要创建绘图相关组件图表类Figure,表示画布上的整个图,管理图形窗口上的子图以及各种图表组件的绘制;
3,然后创建Axes子图类绘制子图,一个Figure上可以有多个子图,一个子图上所有元素都是由Axes管理,包括坐标轴类(Axis),曲线类(Line2D),文本类(Text),图例类等(Legend),当创建一个Axes对象时,会同时自动创建x轴y轴,对子图上各个子对象进行操作。
例如:
axes = self.MainUI.widget.figure.add_subplot(1,1,1)#在已经创建的UI上创建一个子图
axes.set_xlim(0,9)#x轴范围
axes.set_xlabel(“distance[m]”)#横坐标标签
axes.grid(b = True,which = ‘major’,axis = ‘both’)网格
t = []
s = []
for i in range(10):
t.append(i)
s.append(random.randint(0,1500))
axes.plot(t, s,picker=True)#画曲线图
axes.cla()#清除子图内容
self.MainUI.widget.redraw()#对子图执行完各种操作之后,及时刷新
#self.figure.canvas.draw()
具体接口以及说明见:matplotlib.axes接口使用说明

交互功能

NavigationToolbar工具栏

创建NavigationToolbar工具栏时,传递一个FigureCanvas对象作为参数,关联FigureCanvas类对象。
naviBar = NavigationToolbar(figCanvas,self)#创建工具栏
NavigationToolbar父类是QToolbar,可以使用QToolbar的一些接口函数改造工具栏。

FigureCanvas提供的事件

事件名称 触发动作
button_press_event 鼠标按键按下
button_release_event 鼠标按键释放
motion_notify_event 鼠标移动
scroll_event 鼠标滚轮动作
key_press_event 键盘按键按下
key_release_event 键盘按键释放
pick_event 对象被拾取
figure_enter_event 鼠标进入一个Figure对象
figure_leave_event 鼠标离开一个Figure对象
axes_enter_event 鼠标进入一个子图
axes_leave_event 鼠标离开一个子图

鼠标和键盘操作产生的事件,有如下属性:
x,y:画布上x,y的位置,单位像素;
inaxes:产生鼠标事件的Axes子图对象;
xdata,ydata:鼠标光标处x,y的坐标值

FigureCanvas类中,有两个函数用来创建和解除事件与槽函数之间的关联:
1,将事件与槽函数关联mpl_connect(eventName,function),eventName类型为字符串,为上述事件名称,function为连接到的槽函数,返回一个编号,用来标志此事件:
self.__cid = figCanvas.mpl_connect(“scroll_event”,self.do_scrollZoom)#支持鼠标滚轮缩放
2,解除事件关联mpl_disconnect(self.__cid)

自定义一个QmyFigureCanvas类

下面代码自定义了一个QmyFigureCanvas类,继承于QWidget类,作为一个绘图组件,即在Qt Designer设计界面时,将一个QWidget组件提升为QmyFigureCanvas即可。

from PyQt5.QtWidgets import QWidget
from PyQt5 import QtCore
from matplotlib.backends.backend_qt5agg import (FigureCanvasQTAgg as FigureCanvas,NavigationToolbar2QT as NavigationToolbar)#用户界面后端渲染,用来以绘图的形式输出
from PyQt5.QtWidgets import QVBoxLayout
from matplotlib.figure import Figure#图表类
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy

class QmyFigureCanvas(QWidget):
    mouseMove = QtCore.pyqtSignal(numpy.float64,mpl.lines.Line2D)#自定义触发信号,用于与UI交互
    # mousePress = QtCore.pyqtSignal(numpy.float64,numpy.float64)
    # mouseRelease = QtCore.pyqtSignal(numpy.float64,numpy.float64)
    def __init__(self,parent=None,toolbarVisible=True,showHint=False):
        super().__init__(parent)
        # self.figure = mpl.figure.Figure()#公共属性figure
        self.figure = Figure()#公共属性figur
        figCanvas = FigureCanvas(self.figure)#创建FigureCanvas对象
        self.naviBar = NavigationToolbar(figCanvas,self)#创建工具栏
        
        actList = self.naviBar.actions()
        count = len(actList)
        self.__lastActtionHint = actList[count-1]
        self.__showHint = showHint#是否显示坐标提示
        self.__lastActtionHint.setVisible(self.__showHint)
        self.__showToolbar = toolbarVisible#是否显示工具栏
        self.naviBar.setVisible(self.__showToolbar)

        layout = QVBoxLayout(self)
        layout.addWidget(self.naviBar)#添加工具栏
        layout.addWidget(figCanvas)#添加FigureCanvas对象
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)

        self.__cid = figCanvas.mpl_connect("scroll_event",self.do_scrollZoom)#支持鼠标滚轮缩放
        self.__cid1 = figCanvas.mpl_connect("pick_event",self.do_series_pick)#支持曲线抓取
        # self.__cid2 = figCanvas.mpl_connect("button_press_event",self.do_pressMouse)#支持鼠标按下
        self.__cid3 = figCanvas.mpl_connect("button_release_event",self.do_releaseMouse)#支持鼠标释放
        self.__cid4 = figCanvas.mpl_connect("motion_notify_event",self.do_moveMouse)#支持鼠标移动
        self.mouseIsPress = False
        self.pickStatus = False

	#公共函数接口
    def setToolbarVisible(self,isVisible=True):#是否显示工具栏
        self.__showToolbar = isVisible
        self.naviBar.setVisible(isVisible)

    def setDataHintVisible(self,isVisible=True):#是否显示坐标提示
        self.__showHint = isVisible
        self.__lastActtionHint.setVisible(isVisible)

    def redraw(self):#重绘曲线,快速调用
        self.figure.canvas.draw()

    def do_scrollZoom(self,event):#通过鼠标滚轮缩放
        ax = event.inaxes    #产生事件axes对象
        if ax == None:
            return
        self.naviBar.push_current()
        xmin,xmax = ax.get_xbound()
        xlen = xmax - xmin
        ymin,ymax = ax.get_ybound()
        ylen = ymax - ymin

        xchg = event.step * xlen / 20
        xmin = xmin + xchg
        xmax = xmax - xchg
        ychg = event.step * ylen / 20
        ymin = ymin + ychg
        ymax = ymax - ychg
        ax.set_xbound(xmin,xmax)
        ax.set_ybound(ymin,ymax)
        event.canvas.draw()
        
	def do_series_pick(self,event):#picker事件获取抓取曲线
	        self.series = event.artist
	        # index = event.ind[0]
	        # print("series",event.ind)
	        if isinstance(self.series,mpl.lines.Line2D):
	             self.pickStatus = True
        
    def do_releaseMouse(self,event):#鼠标释放,释放抓取曲线
        if event.inaxes == None:
            return
        if self.pickStatus == True:
            self.series.set_color(color = "black")
            self.figure.canvas.draw()
            self.pickStatus = False
        # self.mouseRelease.emit(event.xdata,event.ydata)

    def do_moveMouse(self,event):#鼠标移动,重绘抓取曲线
        if event.inaxes == None:
            return
        if self.pickStatus == True:
            self.series.set_xdata([event.xdata,event.xdata])
            self.series.set_color(color = "red")
            self.figure.canvas.draw()
            self.mouseMove.emit(event.xdata,self.series)#自定义触发信号,用于与UI交互

代码部分创建了一个包含工具栏的Figure()图表组件,并且自定义了鼠标滚轮缩放事件,以及当鼠标抓取直线后,进行直线在坐标范围内平移操作。

应用效果事例

将自定义的QmyFigureCanvas应用于UI中,在UI中随机绘制曲线,并添加axvline直线作为标志线,可拖动标志线进行其他操作显示,如图:
在这里插入图片描述

参考图书:Python Qt GUI与数据可视化编程

猜你喜欢

转载自blog.csdn.net/Lhhxxdhr/article/details/108714777
今日推荐