Pyside2中嵌入Matplotlib的绘图

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

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

1. 界面设计

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

 

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方法呈现图形

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

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 和 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_())

 

 

 

  • 25
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
### 回答1: 如何在 PySide2 使用 Matplotlib? 在 PySide2 使用 Matplotlib 需要先安装 Matplotlib,然后在 PySide2 程序引入 Matplotlib 模块,通过创建 Matplotlib 的 Figure 对象和 AxesSubplot 对象来进行图像绘制操作。 ### 回答2: Pyside2是一个Python GUI开发框架,它可以用于Python GUI应用程序的开发和设计。而matplotlib是一个Python数据可视化库,它可以用于绘制各种类型的图表。当我们使用PySide2开发应用时,我们经常需要将matplotlib集成到应用程序。下面是如何在PySide2嵌入matplotlib的步骤: 第一步:安装matplotlibPySide2库 在使用matplotlib之前,你需要先安装PySide2matplotlib库。 这可以通过pip命令完成: ```python pip install PySide2 pip install matplotlib ``` 当然,你也可以在anaconda环境下安装。 第二步:创建一个空白的PySide2应用程序 接下来,你需要创建一个PySide2应用程序来嵌入matplotlib。你可以使用Qt Designer来创建一个空白窗口或者在PySide2直接编写代码。 第三步:创建一个matplotlib figure 接下来,你需要在PySide2应用程序创建一个matplotlib figure,并将其绘制到Canvas上。你可以使用如下代码: ```python from matplotlib.figure import Figure from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas # 创建Figure figure = Figure() # 创建Canvas canvas = FigureCanvas(figure) ``` 第四步:在figure上绘制图形 接下来,你需要在figure上绘制你想要的图形。可以是柱形图、折线图等。 ```python # 绘制柱形图 import numpy as np x = np.array([1, 2, 3, 4, 5]) y = np.array([2, 4, 6, 8, 10]) ax = figure.add_subplot(111) ax.bar(x, y) ax.set_title("Bar chart") ``` 第五步:将Canvas添加到PySide2应用程序 最后,你需要将Canvas添加到PySide2应用程序的窗口。你可以使用如下代码: ```python # 添加到布局 layout.addWidget(canvas) # 显示界面 window.show() ``` 上述代码的layout为PySide2应用程序的布局管理器,window为PySide2应用程序的主窗口。 这样,你就可以成功地将matplotlib嵌入PySide2应用程序了。当然,你还可以对绘图进行更多的设置和调整,比如:设置X轴、Y轴标签、颜色等。 ### 回答3: 在PythonMatplotlib是一个非常强大的绘图库,它可以用于绘制各种类型的图像和图表。在使用Matplotlib时,有时需要将它嵌入到GUI应用程序,以便用户可以通过应用程序与图像进行交互。而Pyside2是一种Python GUI工具包,它允许开发人员使用Qt框架创建功能强大的GUI应用程序。在本文,我们将介绍如何使用Pyside2嵌入Matplotlib,以便开发人员可以创建自定义GUI应用程序。 在使用Pyside2嵌入Matplotlib之前,需要安装Pyside2Matplotlib库。可以使用pip或conda安装这两个库。安装完成后,就可以开始在Pyside2应用程序使用Matplotlib了。 一个简单的例子是创建一个Qt MainWindow并将Matplotlib嵌入。可以通过以下代码来实现: ``` python from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure import sys class MainWindow(QMainWindow): def __init__(self): super().__init__() # 创建Matplotlib图表 self.plotWidget = QWidget(self) self.setCentralWidget(self.plotWidget) self.plotCanvas = FigureCanvas(Figure(figsize=(5, 3))) lay = QVBoxLayout(self.plotWidget) lay.addWidget(self.plotCanvas) # 绘制数据到Matplotlib图表 ax = self.plotCanvas.figure.subplots() ax.plot([0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]) ax.set_title("Matplotlib图表") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` 在这个例子,我们创建了一个继承自QMainWindow的自定义Qt主窗口,并将Matplotlib图表嵌入Matplotlib图表使用FigureCanvas来渲染,然后通过布局管理器添加到Qt主窗口。最后,在Matplotlib图表使用subplot方法绘制数据。 总之,使用Pyside2嵌入Matplotlib是一个非常有用的功能,允许开发人员创建自定义GUI应用程序并实现交互性的可视化。无论是为科学家设计的数据可视化工具,还是为工程师设计的图表报表,Pyside2嵌入Matplotlib都是非常重要的一步。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值