您的位置:首页 > 编程语言 > Qt开发

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

2018-12-21 20:59 2586 查看
版权声明: https://blog.csdn.net/qq_40587575/article/details/85171401

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

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

1、使用QT Designer实现UI 界面

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

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

 

这是自动生成的代码:

[code]# -*- 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"))
s
3ff7
elf.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,勾选信号类型,点击确定,自动生成代码

[code]# -*- 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())

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

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

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

[code]# -*- 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 函数

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

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

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

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

[code]        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 函数

[code]        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 模块。

使用

[code]            sip.delete(self.F)
sip.delete(self.mpl_ntb)

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

 

 

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

最后显示结果:

 

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐