zoukankan      html  css  js  c++  java
  • 使用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:PyQtpaper_test	est_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控件,更新显示。

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

    最后显示结果:

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

  • 相关阅读:
    find 用法
    linux 查看链接库的版本
    虚函数重载(overwrite) 继承覆盖问题
    将iso mount 到nfs 目录问题
    centos 下使用 pytesseract 识别文字
    nginx 报错Malformed HTTP request line, git 报错fatal: git-write-tree: error building trees
    nfs 支持ipv6
    数位操作
    二分图(最小顶点覆盖 最大匹配 最大独立集 )
    欧几里得算法
  • 原文地址:https://www.cnblogs.com/junge-mike/p/12761369.html
Copyright © 2011-2022 走看看