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的设计模式编程入门指南
Apr 02 Python
python实现数据写入excel表格
Mar 25 Python
浅谈pandas中DataFrame关于显示值省略的解决方法
Apr 08 Python
关于python列表增加元素的三种操作方法
Aug 22 Python
一个可以套路别人的python小程序实例代码
Apr 09 Python
Pytorch抽取网络层的Feature Map(Vgg)实例
Aug 20 Python
通过python3实现投票功能代码实例
Sep 26 Python
python基于socket实现的UDP及TCP通讯功能示例
Nov 01 Python
用Python在Excel里画出蒙娜丽莎的方法示例
Apr 28 Python
django在开发中取消外键约束的实现
May 20 Python
Pytorch转onnx、torchscript方式
May 25 Python
记录一下scrapy中settings的一些配置小结
Sep 28 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环境配置 php5 mysql5 apache2 phpmyadmin安装与配置
2006/11/17 PHP
PHP更新购物车数量(表单部分/PHP处理部分)
2013/05/03 PHP
php遍历目录与文件夹的多种方法详解
2013/11/14 PHP
简介WordPress中用于获取首页和站点链接的PHP函数
2015/12/17 PHP
php 实现一个字符串加密解密的函数实例代码
2016/11/01 PHP
php批量删除操作(数据访问)
2017/05/23 PHP
PHP Laravel 上传图片、文件等类封装
2017/08/16 PHP
PHP7内核之Reference详解
2019/03/14 PHP
JavaScript 面向对象编程(2) 定义类
2010/05/18 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
2012/01/21 Javascript
js获取下拉列表框中的value和text的值示例代码
2014/01/11 Javascript
用jquery的方法制作一个简单的导航栏
2014/06/23 Javascript
javascript实时显示当天日期的方法
2015/05/20 Javascript
JavaScript实现垂直滚动条效果
2017/01/18 Javascript
把JavaScript代码改成ES6语法不完全指南(分享)
2017/09/10 Javascript
Nodejs Express 通过log4js写日志到Logstash(ELK)
2018/08/30 NodeJs
优雅的将ElementUI表格变身成树形表格的方法步骤
2019/04/11 Javascript
纯JS实现五子棋游戏
2020/05/28 Javascript
如何使用jQuery操作Cookies方法解析
2020/09/08 jQuery
[54:02]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 IG vs VGJ.T
2018/04/03 DOTA
Python基础篇之初识Python必看攻略
2016/06/23 Python
Python 爬虫多线程详解及实例代码
2016/10/08 Python
Django unittest 设置跳过某些case的方法
2018/12/26 Python
Python生成指定数量的优惠码实操内容
2019/06/18 Python
Python中如何将一个类方法变为多个方法
2019/12/30 Python
python DES加密与解密及hex输出和bs64格式输出的实现代码
2020/04/13 Python
利用4行Python代码监测每一行程序的运行时间和空间消耗
2020/04/22 Python
python模块如何查看
2020/06/16 Python
Python如何截图保存的三种方法(小结)
2020/09/01 Python
利用Python pandas对Excel进行合并的方法示例
2020/11/04 Python
请解释一下webService? 如何用.net实现webService
2014/06/09 面试题
人力资源管理毕业求职信
2014/08/05 职场文书
明星员工获奖感言
2014/08/14 职场文书
八项规定整改方案
2014/10/01 职场文书
护士自荐信怎么写
2015/03/06 职场文书
小程序自定义轮播图圆点组件
2022/06/25 Javascript