@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:
Reference books: Python Qt GUI and data visualization programming