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

本文介绍如何使用Python的PyQt5库和matplotlib结合,根据界面的输入值动态更新显示的matplotlib图形。首先通过QT Designer设计UI界面,接着实现界面与业务逻辑代码分离,最后编写代码增加显示matplotlib图形的功能,包括根据comboBox选择项更新cos函数图像。
摘要由CSDN通过智能技术生成

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

使用的编程语言是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控件,更新显示。

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

最后显示结果:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值