最初在qtdesigner里面看到QwPlot,但经过查阅,发现这是一个已经没有维护的c++的库,虽然可以找到别人做的对应的python库,但使用起来并不方便,这里推荐结合matplotlib和pyqt5可以实现很好的绘图效果。
在qtdesigner中做这样一个界面,这里我就简单放一个graohicsView,注意这里的宽度和高度,最好和后面画图时的figure相匹配。
用.ui文件生成的.py文件内容如下,当然你也可以跳过UI,直接用这个文件测试
Test_UI.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Test_UI.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
#
# 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(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(150, 120, 500, 300))
self.graphicsView.setObjectName("graphicsView")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 28))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
这里后面的操作可以分为两种方法,这里推荐第二种方法,第一种作为理解的参考
以下最小示例设置了一个 Matplotlib 画布FigureCanvasQTAgg,该画布创建Figure并添加了一组轴。这个画布对象也是一个QWidget,因此可以像任何其他 Qt 小部件一样直接嵌入到应用程序中。
class Figure_Canvas(FigureCanvas): # 通过继承FigureCanvas类,使得该类既是一个PyQt5的Qwidget,又是一个matplotlib的FigureCanvas,这是连接pyqt5与matplot lib的关键
def __init__(self, parent=None, width=5, height=3, dpi=100):
fig = Figure(figsize=(width, height), dpi=100) # 创建一个Figure,注意:该Figure为matplotlib下的figure,不是matplotlib.pyplot下面的figure
FigureCanvas.__init__(self, fig) # 初始化父类
self.setParent(parent)
self.axes = fig.add_subplot(111) # 调用figure下面的add_subplot方法,类似于matplotlib.pyplot下面的subplot方法
def test(self):
x = [1,2,3,4,5,6,7,8,9]
y = [23,21,32,13,3,132,13,3,1]
self.axes.plot(x, y)
这里继承我们之前的界面,执行画图操作,将绘制的图放入QGraphicsView,进行显示
class Test_window(QtWidgets.QMainWindow,Test_UI.Ui_MainWindow):
def __init__(self,parent=None):
super(Test_window,self).__init__(parent)
self.setupUi(self)
dr = Figure_Canvas()
# 实例化一个FigureCanvas
time1 =time.time()
dr.test() # 画图
graphicscene = QtWidgets.QGraphicsScene() # 第三步,创建一个QGraphicsScene,因为加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
graphicscene.addWidget(dr) # 第四步,把图形放到QGraphicsScene中,注意:图形是作为一个QWidget放到QGraphicsScene中的
self.graphicsView.setScene(graphicscene) # 第五步,把QGraphicsScene放入QGraphicsView
self.graphicsView.show() # 最后,调用show方法呈现图形!
time2 = time.time()
print(time2-time1)
总的就是形成这样一个文件
test_qt.py
import matplotlib
matplotlib.use("Qt5Agg") # 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt5 import QtWidgets,QtCore
from PyQt5.QtWidgets import QMainWindow,QApplication
import sys
import Test_UI
import time
class Figure_Canvas(FigureCanvas): # 通过继承FigureCanvas类,使得该类既是一个PyQt5的Qwidget,又是一个matplotlib的FigureCanvas,这是连接pyqt5与matplot lib的关键
def __init__(self, parent=None, width=5, height=3, dpi=100):
fig = Figure(figsize=(width, height), dpi=100) # 创建一个Figure,注意:该Figure为matplotlib下的figure,不是matplotlib.pyplot下面的figure
FigureCanvas.__init__(self, fig) # 初始化父类
self.setParent(parent)
self.axes = fig.add_subplot(111) # 调用figure下面的add_subplot方法,类似于matplotlib.pyplot下面的subplot方法
def test(self):
x = [1,2,3,4,5,6,7,8,9]
y = [23,21,32,13,3,132,13,3,1]
self.axes.plot(x, y)
class Test_window(QtWidgets.QMainWindow,Test_UI.Ui_MainWindow):
def __init__(self,parent=None):
super(Test_window,self).__init__(parent)
self.setupUi(self)
dr = Figure_Canvas()
# 实例化一个FigureCanvas
time1 =time.time()
dr.test() # 画图
graphicscene = QtWidgets.QGraphicsScene() # 第三步,创建一个QGraphicsScene,因为加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
graphicscene.addWidget(dr) # 第四步,把图形放到QGraphicsScene中,注意:图形是作为一个QWidget放到QGraphicsScene中的
self.graphicsView.setScene(graphicscene) # 第五步,把QGraphicsScene放入QGraphicsView
self.graphicsView.show() # 最后,调用show方法呈现图形!
time2 = time.time()
print(time2-time1)
if __name__ == '__main__':
app = QApplication(sys.argv)
mytest = Test_window()
mytest.show()
app.exec_()
方法1是网上常见的方法我在使用中发现,其不能直接把matplotlib.pyplot 的东西拿来用,所以我测试了这样的做法,发现是可行的,这样就可以直接使用pyplot的方法了
def plot_test(self):
figure = plt.figure(figsize=(4, 2), dpi=100)
canvas = FigureCanvas(figure)
x = np.arange(1, 1000)
y = x ** 2
plt.plot(x, y)
canvas.draw() # 这是关键
return canvas
观察这个函数我们可知还是直接用的plt.figure,这个和方法1就区分开了,后面我们还是用FigureCanvas把这个figure进行包装得到canvas,后续的操作完全按照plt画就行了,最后一定加上canvas,draw(),再返回这个canvas就可以直接再pyqt里面显示
完整代码
import matplotlib
matplotlib.use("Qt5Agg") # 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
from PyQt5 import QtWidgets,QtCore
from PyQt5.QtWidgets import QMainWindow,QApplication
import sys
import Test_UI
import time
class Test_window(QtWidgets.QMainWindow,Test_UI.Ui_MainWindow):
def __init__(self,parent=None):
super(Test_window,self).__init__(parent)
self.setupUi(self)
canvas = self.plot_test()
graphicscene = QtWidgets.QGraphicsScene() # 第三步,创建一个QGraphicsScene,因为加载的图形(FigureCanvas)不能直接放到graphicview控件中,必须先放到graphicScene,然后再把graphicscene放到graphicview中
graphicscene.addWidget(canvas) # 第四步,把图形放到QGraphicsScene中,注意:图形是作为一个QWidget放到QGraphicsScene中的
self.graphicsView.setScene(graphicscene) # 第五步,把QGraphicsScene放入QGraphicsView
self.graphicsView.show() # 最后,调用show方法呈现图形!
def plot_test(self):
figure = plt.figure(figsize=(4, 2), dpi=100)
canvas = FigureCanvas(figure)
x = np.arange(1, 1000)
y = x ** 2
plt.plot(x, y)
canvas.draw() # 这是关键
return canvas
if __name__ == '__main__':
app = QApplication(sys.argv)
mytest = Test_window()
mytest.show()
app.exec_()