许多其他 Python 库——例如
seaborn
和pandas
——利用Matplotlib
后端进行绘图。这些绘图可以以与此处所示相同的方式嵌入到 PyQt5 中,并且在绘图时传递对轴的引用
安装 Matplotlib
如果没有安装,您可以使用 Pip 正常安装它,使用以下命令 -
pip install matplotlib
一个简单的例子
import sys
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
class MplCanvas(FigureCanvasQTAgg):
"""
figure 模块提供了顶级 Artist,即 Figure,其中包含所有绘图元素。
该模块用于控制所有绘图元素的子图和顶级容器的默认间距
使用的目的plt.figure()是创建一个图形对象。
整个图形被视为图形对象。当我们想要调整图形的大小以及想要在单个图形中添加多个 Axes 对象时,
必须显式使用
add_subplot添加一个绘图区作为子图排列的一部分,网格“111”表示“1x1 网格,第一个子图
"""
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
# 创建 maptlotlib FigureCanvas 对象,
# 绘制二维坐标轴.
sc = MplCanvas(self, width=5, height=4, dpi=100)
sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])
self.setCentralWidget(sc)
self.show()
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()
带有绘图控件
import sys
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtGui, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
class MplCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
sc = MplCanvas(self, width=5, height=4, dpi=100)
sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])
# 创建工具栏,将canvas作为第一个参数,parent (self,MainWindow) 作为第二个参数
toolbar = NavigationToolbar(sc, self)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(toolbar)
layout.addWidget(sc)
# 创建一个占位小部件来放置固定工具栏和画布.
widget = QtWidgets.QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
self.show()
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()
清除重绘
import sys
import random
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
self.setCentralWidget(self.canvas)
n_data = 50
self.xdata = list(range(n_data))
self.ydata = [random.randint(0, 10) for i in range(n_data)]
self.update_plot()
self.show()
# 通过调用 update_plot 设置定时器进行定时重绘.
self.timer = QtCore.QTimer()
self.timer.setInterval(100)
self.timer.timeout.connect(self.update_plot)
self.timer.start()
def update_plot(self):
# 移除y的一个数据, 添加一个新的数据.
self.ydata = self.ydata[1:] + [random.randint(0, 10)]
self.canvas.axes.cla() # Clear the canvas.
self.canvas.axes.plot(self.xdata, self.ydata, 'r')
# 触发画布更新和重绘.
self.canvas.draw()
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()
动态原地更新
import sys
import random
import matplotlib
matplotlib.use('Qt5Agg')
from PyQt5 import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
self.setCentralWidget(self.canvas)
n_data = 50
self.xdata = list(range(n_data))
self.ydata = [random.randint(0, 10) for i in range(n_data)]
# 只需要一个附加变量检索对绘制线的引用
self._plot_ref = None
self.update_plot()
self.show()
# 通过调用 update_plot 设置定时器进行定时重绘.
self.timer = QtCore.QTimer()
self.timer.setInterval(100)
self.timer.timeout.connect(self.update_plot)
self.timer.start()
def update_plot(self):
# 移除y的一个数据, 添加一个新的数据.
self.ydata = self.ydata[1:] + [random.randint(0, 10)]
# 注意: 不需要清除y的数据.
if self._plot_ref is None:
# 第一次进来self._plotref是None(即没有画线)
# 然后画线并赋值给self._plot_ref
# plot返回的是一个包含一个线条的列表
plot_refs = self.canvas.axes.plot(self.xdata, self.ydata, 'r')
self._plot_ref = plot_refs[0]
else:
# 通过设置更新Y self._plot_ref.set_ydata(self.ydata)
self._plot_ref.set_ydata(self.ydata)
# 更新画布.
self.canvas.draw()
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()