⽤Matplotlib在PyQt5界⾯绘制动态曲线、柱形、⼆维、三维图(上)
⽂章⽬录
前⾔
使⽤PyQt设计程序界⾯过程中不可避免地需要将数据通过图形化的⽅式显⽰出来,对于⼀些实时性较强的系统,还需要能够动态地更新这些图形。然⽽Matplotlab对于曲线图、柱形图、⼆维图、三维图的绘制和更新各有不同的⽅法。
  我在⼯作中就遇到了这个问题,花了不少精⼒汇总了使⽤Matplotlib实现曲线、柱形图、⼆维图以及三维图在PyQt5界⾯中的绘制⽅法以及使其动态更新的⽅法。本系列博客分成两篇,第⼀篇介绍以上四种图形的静态显⽰⽅法,介绍各图形的动态更新⽅法。
  下⾯我们来介绍静态图⽚的显⽰⽅法。
  当然⾸先,我们要配置好⼯作的环境,我使⽤的是python3.6+PyCharm,安装好PyQt5、QtDesigner和matplotlib扩展包,安装⽅式可以参考。
1、准备PyQt界⾯
使⽤PyQt5绘制Matplotlib图形通常可以使⽤QGroupBox、QGraphicsView等⽅式,各有不同的⽤法,我使⽤的是QGroupBox,个⼈感觉它使⽤起来最简单。
  接下来,我们先使⽤QtDesigner创建⼀个主窗⼝,然后在其中创建四个QGroupBox分别⽤来显⽰曲线图、柱形图、⼆维图和三维图。创建后的效果如下图所⽰:
将其保存为DataDIsplayUI.ui,然后通过PyUIC将其转换成DataDIsplayUI.py⽂件,具体实现⽅法可以参考。转换后的py代码如下所⽰,当然我们其实不⽤关⼼它的具体内容,只要会使⽤它就可以了。
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'DataDisplayUI.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
self.LineDisplayGB = QtWidgets.alwidget)
self.LineDisplayGB.setObjectName("LineDisplayGB")
self.BarDisplayGB = QtWidgets.alwidget)
self.BarDisplayGB.setObjectName("BarDisplayGB")
self.ImageDisplayGB = QtWidgets.alwidget)
self.ImageDisplayGB.setObjectName("ImageDisplayGB")
self.SurfaceDisplayGB = QtWidgets.alwidget)
self.SurfaceDisplayGB.setObjectName("SurfaceDisplayGB")
MainWindow.alwidget)
MainWindow.ubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
tSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = anslate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.LineDisplayGB.setTitle(_translate("MainWindow", "Line Display"))
self.BarDisplayGB.setTitle(_translate("MainWindow", "Bar Display"))
self.ImageDisplayGB.setTitle(_translate("MainWindow", "Image Display"))
self.SurfaceDisplayGB.setTitle(_translate("MainWindow", "3D Surface Display"))接下来,创建⼀个新的py⽂件,输⼊以下代码:
from DataDisplayUI import Ui_MainWindow
from PyQt5.QtWidgets import QApplication,QMainWindow,QGridLayout
from PyQt5.QtCore import QTimer
import sys,time
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.lines import Line2D
import matplotlib
import matplotlib.cbook as cbook
class ImgDisp(QMainWindow,Ui_MainWindow):
def __init__(self,parent=None):
super(ImgDisp,self).__init__(parent)
self.setupUi(self)
if __name__=='__main__':
app=QApplication(sys.argv)
matplotlib中subplotui=ImgDisp()
ui.show()
<_())
保存后运⾏,即可看到我们设计的程序界⾯,如下图所⽰。关于上⾯这段代码,需要进⾏⼀下说明,
第⼀⾏导⼊的是我们刚使⽤PyUIC⽣成的py⽂件中的界⾯类,QTimer⽤来将来动态更新我们的图⽚,Matplotlib模块⽤来绘制图形。
2、定义画板
接下来,仍然在这个⽂件中,我们定义⼀个新的类⽤来创建画板,内容如下:
class Figure_Canvas(FigureCanvas):
def __init__(self,parent=None,width=3.9,height=2.7,dpi=100):
self.fig=Figure(figsize=(width,height),dpi=100)
super(Figure_Canvas,self).__init__(self.fig)
self.ax=self.fig.add_subplot(111)
def test(self):
x=[1,2,3,4,5,6,7]
y=[2,1,3,5,6,4,3]
self.ax.plot(x,y)
这个类继承⾃FigureCanvas类,其中width和height分别定义了画板的宽和⾼,单位是100(dpi)像素。这⾥创建了⼀个图self.fig,,最终的图形是显⽰在轴⾥的,⼀个图⾥可以添加多个轴,这些概念与Matlab中的figure和axis⼀样。st函数调⽤后会在轴上画⼀个曲线图,⽤来测试画板创建是否成功。
3、添加画板
接下来,回到我们的界⾯类中,定义⼀些新的函数在四个QGroupBox中分别添加画板:
class ImgDisp(QMainWindow,Ui_MainWindow):
def __init__(self,parent=None):
super(ImgDisp,self).__init__(parent)
self.setupUi(self)
self.Init_Widgets()
def Init_Widgets(self):
self.PrepareSamples()
self.PrepareLineCanvas()
self.PrepareBarCanvas()
self.PrepareImgCanvas()
self.PrepareSurfaceCanvas()
def PrepareSamples(self):
self.x = np.arange(-4, 4, 0.02)
self.y = np.arange(-4, 4, 0.02)
self.X, self.Y = np.meshgrid(self.x, self.y)
self.z = np.sin(self.x)
self.R = np.sqrt(self.X ** 2 + self.Y ** 2)
self.Z = np.sin(self.R)
def PrepareLineCanvas(self):
self.LineFigure = Figure_Canvas()
self.LineFigureLayout = QGridLayout(self.LineDisplayGB)
self.LineFigureLayout.addWidget(self.LineFigure)
self.LineFigure.ax.set_xlim(-4, 4)
self.LineFigure.ax.set_ylim(-1, 1)
self.line = Line2D(self.x, self.z)
self.LineFigure.ax.add_line(self.line)
def PrepareBarCanvas(self):
self.BarFigure = Figure_Canvas()
self.BarFigureLayout = QGridLayout(self.BarDisplayGB)
self.BarFigureLayout.addWidget(self.BarFigure)
self.BarFigure.ax.set_xlim(-4, 4)
self.BarFigure.ax.set_ylim(-1, 1)
self.bar = self.BarFigure.ax.bar(np.arange(-4, 4, 0.5), np.sin(np.arange(-4, 4, 0.5)), width=0.4)
self.patches = self.bar.patches
def PrepareImgCanvas(self):
self.ImgFigure = Figure_Canvas()
self.ImgFigureLayout = QGridLayout(self.ImageDisplayGB)
self.ImgFigureLayout.addWidget(self.ImgFigure)
self.ImgFig = self.ImgFigure.ax.imshow(self.Z, cmap='bone')
self.ImgFig.set_clim(-0.8,0.8)
def PrepareSurfaceCanvas(self):
self.SurfFigure = Figure_Canvas()
self.SurfFigureLayout = QGridLayout(self.SurfaceDisplayGB)
self.SurfFigureLayout.addWidget(self.SurfFigure)
self.ve()
self.ax3d = self.a(projection='3d')
self.Surf = self.ax3d.plot_surface(self.X, self.Y, self.Z, cmap='rainbow')
由于我们要创建四个不同的画板,⽽这些画板的创建⽅式都⼤同⼩异,因此定义⼀个self.Init_Widgets()函数,将所有的画板创建函数都放进去。其中self.PrepareSamples()函数可以⽣成⼀些数据⽤来绘制图形。
4、画图
下⾯结合刚才的代码,详细介绍⼀下画板的创建和不同图形的绘制⽅法。
创建画板

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。