使用PySide2做出一个GUI,并且要将后台使用Matplotlib绘制的图显示在界面上,在网上找到这篇博客解决了自己的需求。所以将学习原博主程序时的记录保留下来。
参考博客:(2条消息) Pyside2中嵌入Matplotlib的绘图_华少的博客-CSDN博客
(2条消息) 解释python参数fig.add_subplot(111)_Mr.Ma-master-CSDN博客
1.使用qt designer设计简单的界面
其中只有两个控件,1.Display Widgets下的Graphics View,并将对象命名为graphicsView,2.Push Button,并将对象命名为btn_sin。
2.定义一个类,继承FigureCanvas
import matplotlib
import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
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):
# 初始化时将图片的长、宽、像素均初始化给定
# 其中xlim,ylim 表示横纵坐标的显示范围
# 创建一个Figure
self.figure = plt.Figure(figsize=(width, height), dpi=dpi, tight_layout=True) # tight_layout: 用于去除画图时两边的空白
FigureCanvas.__init__(self, self.figure) # 初始化父类
self.setParent(parent)
self.fig1 = self.figure.add_subplot(111) # 添加子图
# add_subplot(2,2,4) 添加子图函数,三个参数分别表示纵向分几个子图,横向分几个子图,当前为第几个子图
self.fig1.spines['top'].set_visible(False) # 去掉绘图时上面的横线
self.fig1.spines['right'].set_visible(False) # 去掉绘图时右面的横线
self.fig1.set_xlim(xlim)
self.fig1.set_ylim(ylim)
3.完整代码
from PySide2.QtWidgets import QApplication, QMessageBox, QFileDialog, QGraphicsScene
from PySide2.QtUiTools import QUiLoader
import matplotlib
import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
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):
# 初始化时将图片的长、宽、像素均初始化给定
# 其中xlim,ylim 表示横纵坐标的显示范围
# 创建一个Figure
self.figure = plt.Figure(figsize=(width, height), dpi=dpi, tight_layout=True) # tight_layout: 用于去除画图时两边的空白
FigureCanvas.__init__(self, self.figure) # 初始化父类
self.setParent(parent)
self.fig1 = self.figure.add_subplot(111) # 添加子图
# add_subplot(2,2,4) 添加子图函数,三个参数分别表示纵向分几个子图,横向分几个子图,当前为第几个子图
self.fig1.spines['top'].set_visible(False) # 去掉绘图时上面的横线
self.fig1.spines['right'].set_visible(False) # 去掉绘图时右面的横线
self.fig1.set_xlim(xlim)
self.fig1.set_ylim(ylim)
class Win_Main():
def __init__(self):
self.ui = QUiLoader().load("ui_interactive_test2.ui") # 注意是对ui实例化
self.gv_visual_data_content = MyFigureCanvas(width=self.ui.graphicsView.width()/ 100,
height = self.ui.graphicsView.height() / 100,
xlim =(0, 2 * np.pi),
ylim = (-1, 1)
)
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.fig1.plot(x, y) # 在加在的图形gv_visual_data_content中的子图fig1中画图
self.gv_visual_data_content.fig1.set_title('cos()') # 设置图名
self.graphic_scene = QGraphicsScene() # 创建一个QGraphicsScene
# 加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
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.fig1.clear() # 由于图片需要反复绘制,所以每次绘制前清空,然后绘图
self.gv_visual_data_content.fig1.plot(x, y)
self.gv_visual_data_content.fig1.set_title('sin()')
self.gv_visual_data_content.draw() # 刷新画布显示图片,否则不刷新显示
app = QApplication([])
LoginWin = Win_Main()
LoginWin.ui.show()
app.exec_()