使用PyQt5嵌入matplotlib,实现根据界面输入数值更换显示的matplotlib图形

实现本次博文的功能花了有点时间呀。。。。。。。。。。。。。。。

使用的编程语言是python3.4, 界面设计软件是erics 6结合PyQt5  


1、使用QT Designer实现UI 界面

在eric 6 中,点击项目,新建一个项目,增加如下图的一些控件与布局,不相同都可以。

除了 QVBoxLayout 垂直布局、QPushButton按钮、和comboBox输入widget控件需要注意外,其他的控件都没有使用(即没有使用信号与槽函数),后期可以自行实现其他功能。分别对应上图中的最小的红框、显示图片按钮、显示1的可选控件。

这是自动生成的代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'E:\PyQt\paper_test\test_1.ui'
#
# Created: Fri Dec 21 20:18:35 2018
# by: PyQt5 UI code generator 5.4 # # 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") MainWindow.resize(753, 578) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/pic/cnc.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) MainWindow.setWindowIcon(icon) self.centralWidget = QtWidgets.QWidget(MainWindow) self.centralWidget.setObjectName("centralWidget") self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralWidget) self.horizontalLayout.setObjectName("horizontalLayout") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = QtWidgets.QTabWidget(self.centralWidget) self.tabWidget.setAcceptDrops(False) self.tabWidget.setLayoutDirection(QtCore.Qt.LeftToRight) self.tabWidget.setAutoFillBackground(True) self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded) self.tabWidget.setUsesScrollButtons(False) self.tabWidget.setDocumentMode(True) self.tabWidget.setObjectName("tabWidget") self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.pushButton = QtWidgets.QPushButton(self.tab) self.pushButton.setGeometry(QtCore.QRect(80, 440, 75, 23)) self.pushButton.setObjectName("pushButton") self.pushButton_3 = QtWidgets.QPushButton(self.tab) self.pushButton_3.setGeometry(QtCore.QRect(250, 440, 75, 23)) self.pushButton_3.setObjectName("pushButton_3") self.verticalLayoutWidget_2 = QtWidgets.QWidget(self.tab) self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 20, 521, 371)) self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setObjectName("verticalLayout_2") self.comboBox = QtWidgets.QComboBox(self.tab) self.comboBox.setGeometry(QtCore.QRect(360, 440, 69, 22)) self.comboBox.setObjectName("comboBox") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.comboBox.addItem("") self.tabWidget.addTab(self.tab, "") self.tab_2 = QtWidgets.QWidget() self.tab_2.setObjectName("tab_2") self.pushButton_2 = QtWidgets.QPushButton(self.tab_2) self.pushButton_2.setGeometry(QtCore.QRect(100, 370, 75, 23)) self.pushButton_2.setObjectName("pushButton_2") self.tabWidget.addTab(self.tab_2, "") self.tab_3 = QtWidgets.QWidget() self.tab_3.setObjectName("tab_3") self.tabWidget.addTab(self.tab_3, "") self.tab_4 = QtWidgets.QWidget() self.tab_4.setObjectName("tab_4") self.tabWidget.addTab(self.tab_4, "") self.tab_5 = QtWidgets.QWidget() self.tab_5.setObjectName("tab_5") self.tabWidget.addTab(self.tab_5, "") self.verticalLayout.addWidget(self.tabWidget) self.horizontalLayout.addLayout(self.verticalLayout) MainWindow.setCentralWidget(self.centralWidget) self.menuBar = QtWidgets.QMenuBar(MainWindow) self.menuBar.setGeometry(QtCore.QRect(0, 0, 753, 23)) self.menuBar.setObjectName("menuBar") self.menu = QtWidgets.QMenu(self.menuBar) self.menu.setObjectName("menu") self.menu_2 = QtWidgets.QMenu(self.menuBar) self.menu_2.setObjectName("menu_2") self.menu_3 = QtWidgets.QMenu(self.menuBar) self.menu_3.setObjectName("menu_3") MainWindow.setMenuBar(self.menuBar) self.actionAciton = QtWidgets.QAction(MainWindow) self.actionAciton.setObjectName("actionAciton") self.actionOpen = QtWidgets.QAction(MainWindow) self.actionOpen.setObjectName("actionOpen") self.actionOpen_2 = QtWidgets.QAction(MainWindow) self.actionOpen_2.setObjectName("actionOpen_2") self.actionAbout = QtWidgets.QAction(MainWindow) self.actionAbout.setObjectName("actionAbout") self.actionShezih = QtWidgets.QAction(MainWindow) self.actionShezih.setObjectName("actionShezih") self.actionBaochun = QtWidgets.QAction(MainWindow) self.actionBaochun.setObjectName("actionBaochun") self.actionXinjian = QtWidgets.QAction(MainWindow) self.actionXinjian.setObjectName("actionXinjian") self.actionLingchunwei = QtWidgets.QAction(MainWindow) self.actionLingchunwei.setObjectName("actionLingchunwei") self.actionAbou2 = QtWidgets.QAction(MainWindow) self.actionAbou2.setObjectName("actionAbou2") self.menu.addAction(self.actionOpen_2) self.menu.addAction(self.actionBaochun) self.menu.addAction(self.actionXinjian) self.menu.addAction(self.actionLingchunwei) self.menu_2.addAction(self.actionShezih) self.menu_3.addAction(self.actionAbout) self.menu_3.addAction(self.actionAbou2) self.menuBar.addAction(self.menu.menuAction()) self.menuBar.addAction(self.menu_2.menuAction()) self.menuBar.addAction(self.menu_3.menuAction()) self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "显示图片")) self.pushButton_3.setText(_translate("MainWindow", "显示2")) self.comboBox.setItemText(0, _translate("MainWindow", "1")) self.comboBox.setItemText(1, _translate("MainWindow", "2")) self.comboBox.setItemText(2, _translate("MainWindow", "3")) self.comboBox.setItemText(3, _translate("MainWindow", "4")) self.comboBox.setItemText(4, _translate("MainWindow", "5")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "文本1")) self.pushButton_2.setText(_translate("MainWindow", "显示2")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "文本2")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "文本3")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "文本4")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_5), _translate("MainWindow", "文本5")) self.menu.setTitle(_translate("MainWindow", "文件")) self.menu_2.setTitle(_translate("MainWindow", "设置")) self.menu_3.setTitle(_translate("MainWindow", "帮助")) self.actionAciton.setText(_translate("MainWindow", "about")) self.actionOpen.setText(_translate("MainWindow", "open")) self.actionOpen_2.setText(_translate("MainWindow", "打开")) self.actionAbout.setText(_translate("MainWindow", "关于")) self.actionShezih.setText(_translate("MainWindow", "设置1")) self.actionBaochun.setText(_translate("MainWindow", "保存")) self.actionXinjian.setText(_translate("MainWindow", "新建")) self.actionLingchunwei.setText(_translate("MainWindow", "另存为")) self.actionAbou2.setText(_translate("MainWindow", "联系我们")) import my_pic_rc if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_()) 

import my_pic_rc 是我的资源文件,保存着图片文件,eric 6能把其编译成二进制文件

小伙伴们可以删除它

2.实现界面与业务逻辑代码分离

eric6 相对于 wxpython是能实现界面与业务逻辑代码分离

右键点击刚刚创建的.ui 文件,在弹出的选项框中 点击 ‘ 生成对话框代码’ 

‘新建’,输入自定义的类名、文件名、路径名

因为这次的小项目只是使用了 ‘显示图片’这个按钮,对应名称为 pushButton,勾选信号类型,点击确定,自动生成代码

# -*- coding: utf-8 -*-

"""
Module implementing CallTest.
"""

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow from PyQt5 import QtCore, QtGui, QtWidgets import matplotlib matplotlib.use('Qt5Agg') from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from PyQt5 import QtCore, QtWidgets,QtGui import matplotlib.pyplot as plt from Ui_test_1 import Ui_MainWindow class CallTest(QMainWindow, Ui_MainWindow): """ Class documentation goes here. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget @type QWidget """ super(CallTest, self).__init__(parent) self.setupUi(self)  @pyqtSlot() def on_pushButton_clicked(self): """ Slot documentation goes here. """ # TODO: not implemented yet #self.plot_() print(self.comboBox.currentText())

需要显示的话,加上下面的代码

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    demo = CallTest()
    demo.show()
    sys.exit(app.exec_())

3.增加显示matplotlib图形的代码

# -*- coding: utf-8 -*-

"""
Module implementing CallTest.
"""
import sys
import random
import matplotlib from PyQt5.QtCore import pyqtSlot from PyQt5 import QtCore, QtGui, QtWidgets matplotlib.use('Qt5Agg') from PyQt5 import QtCore, QtWidgets,QtGui from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QSizePolicy, QWidget from numpy import arange, sin, pi from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar from matplotlib.figure import Figure import matplotlib.pyplot as plt import numpy as np from Ui_test_1 import Ui_MainWindow import sip #创建一个matplotlib图形绘制类 class MyFigure(FigureCanvas): def __init__(self,width=5, height=4, dpi=100): #第一步:创建一个创建Figure self.fig = Figure(figsize=(width, height), dpi=dpi) #第二步:在父类中激活Figure窗口 super(MyFigure,self).__init__(self.fig) #此句必不可少,否则不能显示图形 #第三步:创建一个子图,用于绘制图形用,111表示子图编号,如matlab的subplot(1,1,1) self.axes = self.fig.add_subplot(111) #第四步:就是画图,【可以在此类中画,也可以在其它类中画】,最好是在别的地方作图 def plotsin(self): self.axes0 = self.fig.add_subplot(111) t = np.arange(0.0, 3.0, 0.01) s = np.sin(2 * np.pi * t) self.axes0.plot(t, s) def plotcos(self): t = np.arange(0.0, 3.0, 0.01) s = np.sin(2 * np.pi * t) self.axes.plot(t, s) class CallTest(QMainWindow, Ui_MainWindow): step = 0 """ Class documentation goes here. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget @type QWidget """ super(CallTest, self).__init__(parent) self.setupUi(self) def myfunction(self): self.F = MyFigure(width=3, height=2, dpi=100) t = np.arange(0.0, int(self.comboBox.currentText()), 0.01) s = np.cos(2 * np.pi * t) self.F.axes.plot(t, s) #使用控件,在widget上作图 self.F.fig.suptitle("cos") if self.verticalLayout_2.count() < 2: self.verticalLayout_2.addWidget(self.F) self.mpl_ntb = NavigationToolbar(self.F, self) # 添加完整的 toolbar,增加图片放大、移动的按钮 self.verticalLayout_2.addWidget(self.mpl_ntb) #此处的代码可以进行显示,如何将图片进行变换 def plotcos(self): self.step += 1 if self.step == 1: self.myfunction() else: sip.delete(self.F) sip.delete(self.mpl_ntb) self.myfunction() print(str(self.step))  @pyqtSlot() def on_pushButton_clicked(self): """ Slot documentation goes here. """ # TODO: not implemented yet # self.mpl.start_static_plot() print('this is button 1') self.plotcos() if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) demo = CallTest() demo.show() sys.exit(app.exec_())

创建一个class MyFigure(FigureCanvas): 类,继承于  FigureCanvas

接下来主要讲下 myfunction 函数和 plotcos 函数

1. myfunction 函数

self.F = MyFigure(width=3, height=2, dpi=100)

 可以理解self.F是一个widget 控件了

t = np.arange(0.0, int(self.comboBox.currentText()), 0.01)

获取comboBox控件的当前选择的值,由于是字符型,需要强制转换成int 型。用于变换cos函数的间距。

        if self.verticalLayout_2.count() < 2: 
            self.verticalLayout_2.addWidget(self.F) 
            self.mpl_ntb = NavigationToolbar(self.F, self)  # 添加完整的 toolbar,增加图片放大、移动的按钮
            self.verticalLayout_2.addWidget(self.mpl_ntb)

当垂直布局中的widget 少于 2个时,将F和 操作图形的控件mpl_ntb 增加到垂直布局中,使用函数addWidget()

最主要是使layout中不一直 增加控件,如果没有if的话,将一直垂直增加控件。

 2.plotcos 函数

        self.step += 1
        if self.step == 1:
            self.myfunction()
        else:
            sip.delete(self.F)
            sip.delete(self.mpl_ntb) 
            self.myfunction()           
            
        print(str(self.step))

初始化的step为0, step用来判断是否是用户第一次显示图形,如果是第一次则创建图形,将其增加到垂直布局中;

如果是要刷新图片,则要先将原始垂直布局layout中的widget 删除。

题外话:本来看到api文档有removeWidget函数的,试过用来删除,但是没用。。。。。。。。但我把一个按钮QPushButton按钮控件加入到垂直布局中,使用removeWidget函数能把按钮控件删除。。。。。。。。。不明觉厉。。。。。。。网上查了好久,才查到使用import sip 模块。

使用

            sip.delete(self.F)
            sip.delete(self.mpl_ntb) 

将原来的两个控件进行删除,然后调用myfunction 函数,再根据comboBox控件,更新显示。

终于。。。。。。。大功告成。。。。。。。。。。。。

最后显示结果:

让我们共同学习,共同进步

猜你喜欢

转载自www.cnblogs.com/junge-mike/p/12761369.html
今日推荐