Pyside2中嵌入Matplotlib的绘图的实现


Posted in Python onFebruary 22, 2021

近期遇到一个需求,就是用PySide2做出一个GUI,并且要将后台使用Matplotlib绘制的图显示在界面上。自己琢磨了蛮久,网上也搜了不少资料,但都感觉参差不齐,所以就自己总结一下。

我们使用QGraphicsView插件来显示Matplotlib里绘制的图片。这里演示的功能为:打开时界面默认绘制 cos函数的图像,点击按钮后,绘制sin函数的图像。

1. 界面设计

简单创建一个界面:一个 GraphicsView 和 一个 PushButton

Pyside2中嵌入Matplotlib的绘图的实现

2. 定义一个类,继承FigureCanvas

import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
# from matplotlib.figure import Figure
import matplotlib.pyplot as plt
 
matplotlib.use("Qt5Agg") # 声明使用QT5
 
 
class MyFigureCanvas(FigureCanvas):
  '''
  通过继承FigureCanvas类,使得该类既是一个PyQt5的Qwidget,又是一个matplotlib的FigureCanvas,这是连接pyqt5与matplotlib的关键
  '''
  def __init__(self, parent=None, width=10, height=5, xlim=(0, 2500), ylim=(-2, 2), dpi=100):
    # 创建一个Figure
    fig = plt.Figure(figsize=(width, height), dpi=dpi, tight_layout=True) # tight_layout: 用于去除画图时两边的空白
 
    FigureCanvas.__init__(self, fig) # 初始化父类
    self.setParent(parent)
 
    self.axes = fig.add_subplot(111) # 添加子图
    self.axes.spines['top'].set_visible(False) # 去掉绘图时上面的横线
    self.axes.spines['right'].set_visible(False) # 去掉绘图时右面的横线
    self.axes.set_xlim(xlim)
    self.axes.set_ylim(ylim)

然后就可以开始绘图了。

3. 绘图并显示

3.1 先初始化一下我们定义的类

这里 self.ui.graphicsView.width() / 101 的作用:

  • 因为直接使用默认绘制出来的图的大小,一般都会与我们窗口里 GraphicsView 的大小不一致,会造成图像显示不完全,需要拖动滚动条看图像。这里我们将绘图的大小设置为与GraphicsView相匹配的大小,就可以显示出全部图像。之所以  "/101",我感觉可能是 graphicsView.width() 得到的结果 和 plt的figsize里设置图大小的参数 的单位是不一样的,所以要除以一个数,让图像能刚好全部显示在GraphicsView里
# 初始化 gv_visual_data 的显示
self.gv_visual_data_content = MyFigureCanvas(width=self.ui.graphicsView.width() / 101,
                       height=self.ui.graphicsView.height() / 101,
                       xlim=(0, 2*np.pi),
                       ylim=(-1, 1)) # 实例化一个FigureCanvas

3.2 接着就开始用Matplotlib绘制cos函数的图像并显示在GraphicsView里

x = np.arange(0, 2 * np.pi, np.pi / 100)
y = np.cos(x)
self.gv_visual_data_content.axes.plot(x, y)
self.gv_visual_data_content.axes.set_title('cos()')
# 加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
self.graphic_scene = QGraphicsScene() # 创建一个QGraphicsScene
self.graphic_scene.addWidget(self.gv_visual_data_content) # 把图形放到QGraphicsScene中,注意:图形是作为一个QWidget放到放到QGraphicsScene中的
self.ui.graphicsView.setScene(self.graphic_scene) # 把QGraphicsScene放入QGraphicsView
self.ui.graphicsView.show() # 调用show方法呈现图形

到这里,已经可以运行看到初步效果了

Pyside2中嵌入Matplotlib的绘图的实现

3.3 接下来实现点击按钮,切换为sin函数图像的功能

先将信号与槽连接好

self.ui.btn_sin.clicked.connect(self.plot_sin)

编写槽函数

def plot_sin(self):
    x = np.arange(0, 2 * np.pi, np.pi / 100)
    y = np.sin(x)
    self.gv_visual_data_content.axes.clear() # 由于图片需要反复绘制,所以每次绘制前清空,然后绘图
    self.gv_visual_data_content.axes.plot(x, y)
    self.gv_visual_data_content.axes.set_title('sin()')
    self.gv_visual_data_content.draw() # 刷新画布显示图片,否则不刷新显示

好了,看看效果

Pyside2中嵌入Matplotlib的绘图的实现

大功告成。

完整代码:

注意:导包时,要将 PySide2 和 UI 的包 放在 matplotlib 相关包 的 前面,不然 里面的 self.graphic_scene.addWidget(self.gv_visual_data_content)  这里会报如下的错!!!

TypeError: 'PySide2.QtWidgets.QGraphicsScene.addWidget' called with wrong argument types:
  PySide2.QtWidgets.QGraphicsScene.addWidget(MyFigureCanvas)
Supported signatures:
  PySide2.QtWidgets.QGraphicsScene.addWidget(PySide2.QtWidgets.QWidget, PySide2.QtCore.Qt.WindowFlags = Default(Qt.WindowFlags))

至于为什么呢?我也不大清楚,不过好像如果使用的是PyQt5的话就没这种问题,玄学吧!!!

from PySide2.QtWidgets import QApplication, QMainWindow, QGraphicsScene, QFileDialog, QMessageBox
from UI.test import Ui_MainWindow
 
import sys
import numpy as np
import matplotlib
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
# from matplotlib.figure import Figure
import matplotlib.pyplot as plt
 
matplotlib.use("Qt5Agg") # 声明使用QT5
 
 
class MyFigureCanvas(FigureCanvas):
  '''
  通过继承FigureCanvas类,使得该类既是一个PyQt5的Qwidget,又是一个matplotlib的FigureCanvas,这是连接pyqt5与matplotlib的关键
  '''
  def __init__(self, parent=None, width=10, height=5, xlim=(0, 2500), ylim=(-2, 2), dpi=100):
    # 创建一个Figure
    fig = plt.Figure(figsize=(width, height), dpi=dpi, tight_layout=True) # tight_layout: 用于去除画图时两边的空白
 
    FigureCanvas.__init__(self, fig) # 初始化父类
    self.setParent(parent)
 
    self.axes = fig.add_subplot(111) # 调用figure下面的add_subplot方法,类似于matplotlib.pyplot下面的subplot方法
    self.axes.spines['top'].set_visible(False) # 去掉上面的横线
    self.axes.spines['right'].set_visible(False)
    self.axes.set_xlim(xlim)
    self.axes.set_ylim(ylim)
 
class MainWindow(QMainWindow):
  def __init__(self):
    super().__init__()
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)
 
    # 初始化 gv_visual_data 的显示
    self.gv_visual_data_content = MyFigureCanvas(width=self.ui.graphicsView.width() / 101,
                           height=self.ui.graphicsView.height() / 101,
                           xlim=(0, 2*np.pi),
                           ylim=(-1, 1)) # 实例化一个FigureCanvas
    self.plot_cos()
 
    self.ui.btn_sin.clicked.connect(self.plot_sin)
 
  def plot_cos(self):
    x = np.arange(0, 2 * np.pi, np.pi / 100)
    y = np.cos(x)
    self.gv_visual_data_content.axes.plot(x, y)
    self.gv_visual_data_content.axes.set_title('cos()')
    # 加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
    self.graphic_scene = QGraphicsScene() # 创建一个QGraphicsScene
    self.graphic_scene.addWidget(self.gv_visual_data_content) # 把图形放到QGraphicsScene中,注意:图形是作为一个QWidget放到放到QGraphicsScene中的
    self.ui.graphicsView.setScene(self.graphic_scene) # 把QGraphicsScene放入QGraphicsView
    self.ui.graphicsView.show() # 调用show方法呈现图形
 
  def plot_sin(self):
    x = np.arange(0, 2 * np.pi, np.pi / 100)
    y = np.sin(x)
    self.gv_visual_data_content.axes.clear() # 由于图片需要反复绘制,所以每次绘制前清空,然后绘图
    self.gv_visual_data_content.axes.plot(x, y)
    self.gv_visual_data_content.axes.set_title('sin()')
    self.gv_visual_data_content.draw() # 刷新画布显示图片,否则不刷新显示
 
 
if __name__ == "__main__":
  app = QApplication(sys.argv)
  win = MainWindow()
  win.show()
  sys.exit(app.exec_())

到此这篇关于Pyside2中嵌入Matplotlib的绘图的实现的文章就介绍到这了,更多相关Pyside2嵌入Matplotlib内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python提示No module named images的解决方法
Sep 29 Python
python执行子进程实现进程间通信的方法
Jun 02 Python
Python验证码识别处理实例
Dec 28 Python
关于python的bottle框架跨域请求报错问题的处理方法
Mar 19 Python
Python多进程库multiprocessing中进程池Pool类的使用详解
Nov 24 Python
Python实现确认字符串是否包含指定字符串的实例
May 02 Python
mac下如何将python2.7改为python3
Jul 13 Python
PyCharm2019安装教程及其使用(图文教程)
Sep 29 Python
Pycharm远程连接服务器并实现代码同步上传更新功能
Feb 25 Python
Pytorch转onnx、torchscript方式
May 25 Python
利用PyQt5+Matplotlib 绘制静态/动态图的实现代码
Jul 13 Python
python简单利用字典破解zip文件口令
Sep 07 Python
Python实现Excel自动分组合并单元格
Feb 22 #Python
matplotlib绘制正余弦曲线图的实现
Feb 22 #Python
Python使用tkinter制作在线翻译软件
Feb 22 #Python
Python中使用Selenium环境安装的方法步骤
Feb 22 #Python
Python爬虫实例之2021猫眼票房字体加密反爬策略(粗略版)
Feb 22 #Python
python实现计算图形面积
Feb 22 #Python
python实现银行账户系统
Feb 22 #Python
You might like
PHP 和 MySQL 基础教程(三)
2006/10/09 PHP
深入PHP变量存储的详解
2013/06/13 PHP
PHP之uniqid()函数用法
2014/11/03 PHP
php使用递归函数实现数字累加的方法
2015/03/16 PHP
PHP简单预防sql注入的方法
2016/09/27 PHP
图片自动缩小 点击放大
2008/07/07 Javascript
JQuery入门—编写一个简单的JQuery应用案例
2013/01/03 Javascript
如何使用jQUery获取选中radio对应的值(一句代码)
2013/06/03 Javascript
跟我学Node.js(四)---Node.js的模块载入方式与机制
2014/06/04 Javascript
JQuery获取与设置HTML元素的内容或文本的实现代码
2014/06/20 Javascript
jquery实现将获取的颜色值转换为十六进制形式的方法
2014/12/20 Javascript
jquery点击缩略图切换视频播放特效代码分享
2015/09/15 Javascript
全面解析Bootstrap图片轮播效果
2015/12/03 Javascript
JavaScript生成验证码并实现验证功能
2016/09/24 Javascript
浅谈React 属性和状态的一些总结
2016/11/21 Javascript
JS实现最简单的冒泡排序算法
2017/02/15 Javascript
Vue.js 点击按钮显示/隐藏内容的实例代码
2018/02/08 Javascript
对layui中表单元素的使用详解
2018/08/15 Javascript
从vue源码解析Vue.set()和this.$set()
2018/08/30 Javascript
浅谈React碰到v-if
2018/11/04 Javascript
详解一个基于套接字实现长连接的express
2019/03/28 Javascript
详谈Vue.js框架下main.js,App.vue,page/index.vue之间的区别
2020/08/12 Javascript
python递归计算N!的方法
2015/05/05 Python
Phantomjs抓取渲染JS后的网页(Python代码)
2016/05/13 Python
Python实现的凯撒密码算法示例
2018/04/12 Python
python各层级目录下import方法代码实例
2020/01/20 Python
Python实现淘宝秒杀功能的示例代码
2021/01/19 Python
python3.9和pycharm的安装教程并创建简单项目的步骤
2021/02/03 Python
玩具反斗城天猫官方旗舰店:享誉全球的玩具店
2017/10/10 全球购物
Gtech官方网站:地毯清洁器、吸尘器及园艺设备
2018/05/23 全球购物
逃课上网检讨书
2014/02/20 职场文书
人事部经理岗位职责
2014/03/07 职场文书
《悯农》教学反思
2014/04/28 职场文书
遗失证明范文
2015/06/19 职场文书
2015年治庸问责工作总结
2015/07/27 职场文书
详解在SQLPlus中实现上下键翻查历史命令的功能
2022/03/18 SQL Server