PyQt5 takes notes and uses Matplotlib to draw

@PyQt5 Take notes and use Matplotlib to draw

The basic process of creating Matplotlib plots on PyQt5

1. To display on the PyQt5 interface, first create the interface component FigureCanvas, a canvas (equivalent to the Widget component used to display Matplotlib);
2. Then you need to create a drawing-related component chart class Figure, which represents the entire picture on the canvas, and manages The drawing of subgraphs and various chart components on the graphics window;
3. Then create an Axes subgraph class to draw subgraphs. There can be multiple subgraphs on a Figure, and all elements on a subgraph are managed by Axes, including coordinate axes. Class (Axis), curve class (Line2D), text class (Text), legend class, etc. (Legend). When an Axes object is created, the x-axis and y-axis will be automatically created at the same time to operate on each sub-object on the subgraph.
For example:
axes = self.MainUI.widget.figure.add_subplot(1,1,1)#Create a subplot on the created UI
axes.set_xlim(0,9)
#x- axis range axes.set_xlabel("distance[ m]”)#horizontal label
axes.grid(b = True,which ='major',axis ='both') grid
t = []
s = []
for i in range(10):
t.append( i)
s.append(random.randint(0,1500))
axes.plot(t, s,picker=True)#画
线图axes.cla()#Clear the contents of the
subgraph self.MainUI.widget.redraw() # subgraph after completing perform various operations, and refresh
#self.figure.canvas.draw() For
specific interfaces and instructions, see: matplotlib.axes interface instructions

Interactive function

NavigationToolbar toolbar

When creating the NavigationToolbar toolbar, pass a FigureCanvas object as a parameter to associate the FigureCanvas class object.
naviBar = NavigationToolbar(figCanvas,self)#Create Toolbar The
parent class of NavigationToolbar is QToolbar. You can use some interface functions of QToolbar to transform the toolbar.

Events provided by FigureCanvas

Event name Trigger action
button_press_event Mouse button down
button_release_event Mouse button release
motion_notify_event Mouse movement
scroll_event Mouse wheel action
key_press_event Keyboard key press
key_release_event Keyboard key release
pick_event Object picked up
figure_enter_event Mouse into a Figure object
figure_leave_event The mouse leaves a Figure object
axes_enter_event Mouse into a sub-picture
axes_leave_event Mouse left a subgraph

The events generated by mouse and keyboard operations have the following attributes:
x, y: the position of x, y on the canvas, unit pixel;
inaxes: the Axes sub-image object that generated the mouse event;
xdata, ydata: the x, y coordinates of the mouse cursor value

In the FigureCanvas class, there are two functions for creating and disassociating events and slot functions:
1. Associate events with slot functions mpl_connect(eventName, function), eventName is a string, which is the name of the above event, and function is The connected slot function returns a number to mark this event:
self.__cid = figCanvas.mpl_connect("scroll_event",self.do_scrollZoom)#Support mouse wheel zoom
2, disassociate event mpl_disconnect(self.__cid)

Customize a QmyFigureCanvas class

The following code customizes a QmyFigureCanvas class, inherited from the QWidget class, as a drawing component, that is, when designing the interface of Qt Designer, a QWidget component can be upgraded to 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交互

The code part creates a Figure() chart component that contains a toolbar, and customizes the zoom event of the mouse wheel, and when the mouse grabs the line, the line is translated within the coordinate range.

Examples of application effects

Apply the customized QmyFigureCanvas to the UI, draw a curve randomly in the UI, and add the axvline line as the mark line. You can drag the mark line to display other operations, as shown in the figure:
Insert picture description here

Reference books: Python Qt GUI and data visualization programming

Guess you like

Origin blog.csdn.net/Lhhxxdhr/article/details/108714777