显示 Matplotlib 图表
这篇教学会介绍如何运用 PyQt6 的 QGraphicsView,在 PyQt6 中显示 Matplotlib 图表,最后还会搭配 QTimer 实作图表动画 ( 不断移动的正弦波形 )。
快速导览:
因为 Google Colab 不支援 PyQt6,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda )。
安装 Matplotlib 和 NumPy 函数库
输入下列指令安装 Matplotlib 和 NumPy 函数库,根据个人环境使用 pip 或 pip3,如果使用 Anaconda Jupyter,已经内建 Matplotlib 和 NumPy 函数库。
pip install matplotlib
pip install numpy
Matplotlib 显示正弦波形
参考“折线图 Line Chart”教学范例,下方的程序码执行后,就会产生 0~2 之间的正弦波形。
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(3,2), dpi=150)
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
line.set_data([], [])
x = np.linspace(0, 2, 100)
y = np.sin(5 * np.pi * x)
line.set_data(x, y)
plt.show()
PyQt6 显示 Matplotlib 图表
如果要在 PyQt6 中显示 Matplotlib 图表,需要额外加载 matplotlib.backends.backend_qt5agg 模组,并将 Matplotlib 设定为使用 Qt5Agg,接着就能透过 PyQt6 的 QGraphicsView 元件显示图表,下方的程序码执行后,会打开 PyQt6 视窗显示 Matplotlib 图表 ( 注意 import 函数库的顺序 )。
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg") # 使用 Qt5
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys
# 建立正弦波繪圖函式
def sinWave(i=0):
fig = plt.figure(figsize=(3,2), dpi=100)
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
line.set_data([], [])
x = np.linspace(0, 2, 100)
y = np.sin(5 * np.pi * (x - 0.01*i))
line.set_data(x, y)
return fig
canvas = FigureCanvas(sinWave()) # 將圖表繪製在 FigureCanvas 裡
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(360, 240)
graphicview = QtWidgets.QGraphicsView(MainWindow) # 建立顯示圖片元件
graphicview.setGeometry(0, 0, 360, 240)
graphicscene = QtWidgets.QGraphicsScene() # 建立場景
graphicscene.setSceneRect(0, 0, 340, 220)
graphicscene.addWidget(canvas) # 場景中放入圖表
graphicview.setScene(graphicscene) # 元件中放入場景
MainWindow.show()
sys.exit(app.exec())
class 写法:
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg") # 使用 Qt5
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys
class mainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(360, 240)
self.ui()
def ui(self):
canvas = FigureCanvas(self.sinWave()) # 將圖表繪製在 FigureCanvas 裡
graphicview = QtWidgets.QGraphicsView(self) # 建立顯示圖片元件
graphicview.setGeometry(0, 0, 360, 240)
graphicscene = QtWidgets.QGraphicsScene() # 建立場景
graphicscene.setSceneRect(0, 0, 340, 220)
graphicscene.addWidget(canvas) # 場景中放入圖表
graphicview.setScene(graphicscene) # 元件中放入場景
def sinWave(self, i=0):
fig = plt.figure(figsize=(3,2), dpi=100)
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
line.set_data([], [])
x = np.linspace(0, 2, 100)
y = np.sin(5 * np.pi * (x - 0.01*i))
line.set_data(x, y)
return fig
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = mainWindow()
Form.show()
sys.exit(app.exec())
PyQt6 显示 Matplotlib 图表动画
能够显示图表后,就能再透过 QTimer 定时器功能,不断改变图表内容,就能实现图表动画的效果 ( 注意,绘制图表时先加入 plt.close() 关闭已存在但不显示的图表,避免图表数量到达上限 )。
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg") # 使用 Qt5
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys
def sinWave(i=0):
plt.close() # 執行時先刪除已有的 plt
fig = plt.figure(figsize=(3,2), dpi=100)
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
line.set_data([], [])
x = np.linspace(0, 2, 100)
y = np.sin(5 * np.pi * (x - 0.01*i))
line.set_data(x, y)
return fig
canvas = FigureCanvas(sinWave())
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowTitle("oxxo.studio")
MainWindow.resize(360, 240)
graphicview = QtWidgets.QGraphicsView(MainWindow)
graphicview.setGeometry(0, 0, 360, 240)
graphicscene = QtWidgets.QGraphicsScene()
graphicscene.setSceneRect(0, 0, 340, 220)
graphicscene.addWidget(canvas)
graphicview.setScene(graphicscene)
dx = 0 # x 位移初始值
def count():
global dx, canvas
dx = dx + 5 # 每次定時器執行位移 5
canvas = FigureCanvas(sinWave(dx)) # 產生新的正弦波圖形
graphicscene.clear() # 清空場景
graphicscene.addWidget(canvas) # 場景放入圖形
timer = QTimer() # 加入定時器
timer.timeout.connect(count) # 設定定時要執行的 function
timer.start(50) # 啟用定時器,設定間隔時間為 500 毫秒
MainWindow.show()
sys.exit(app.exec())
使用 class 写法:
import numpy as np
import matplotlib
matplotlib.use("Qt5Agg") # 使用 Qt5
from PyQt6 import QtWidgets
from PyQt6.QtGui import *
from PyQt6.QtCore import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(360, 240)
self.t = 0
self.ui()
def ui(self):
self.canvas = FigureCanvas(self.sinWave())
self.graphicview = QtWidgets.QGraphicsView(self)
self.graphicview.setGeometry(0, 0, 360, 240)
self.graphicscene = QtWidgets.QGraphicsScene()
self.graphicscene.setSceneRect(0, 0, 340, 220)
self.graphicscene.addWidget(self.canvas)
self.graphicview.setScene(self.graphicscene)
def sinWave(self, i=0):
fig = plt.figure(figsize=(3,2), dpi=100)
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [])
line.set_data([], [])
x = np.linspace(0, 2, 100)
y = np.sin(5 * np.pi * (x - 0.01*i))
line.set_data(x, y)
plt.close()
return fig
def count(self):
self.t = self.t + 5
self.canvas = FigureCanvas(self.sinWave(self.t))
self.graphicscene.clear()
self.graphicscene.addWidget(self.canvas)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
timer = QTimer() # 加入定時器
timer.timeout.connect(Form.count) # 設定定時要執行的 function
timer.start(50) # 啟用定時器,設定間隔時間為 500 毫秒
sys.exit(app.exec())
微信扫码关注
抖音扫码关注