Pyqt+matplotlib 實現(xiàn)實時畫圖案例
需求分析:
項目中根據測得的數據在界面上實時繪制
運行環(huán)境:
Python 3.7 + Matplotlib 3.0.2 + PyQt 5
matplot官網給的相應的例子:
import sys
import time
import numpy as np
from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
if is_pyqt5():
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
else:
from matplotlib.backends.backend_qt4agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(static_canvas)
self.addToolBar(NavigationToolbar(static_canvas, self))
dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(dynamic_canvas)
self.addToolBar(QtCore.Qt.BottomToolBarArea,
NavigationToolbar(dynamic_canvas, self))
self._static_ax = static_canvas.figure.subplots()
t = np.linspace(0, 10, 501)
self._static_ax.plot(t, np.tan(t), ".")
self._dynamic_ax = dynamic_canvas.figure.subplots()
self._timer = dynamic_canvas.new_timer(
100, [(self._update_canvas, (), {})])
self._timer.start()
def _update_canvas(self):
self._dynamic_ax.clear()
t = np.linspace(0, 10, 101)
# Shift the sinusoid as a function of time.
self._dynamic_ax.plot(t, np.sin(t + time.time()))
self._dynamic_ax.figure.canvas.draw()
if __name__ == "__main__":
qapp = QtWidgets.QApplication(sys.argv)
app = ApplicationWindow()
app.show()
qapp.exec_()

上圖中的散點為靜止的,下面的圖為動態(tài)的,類似行波,一直在行走,是應為用了**self._dynamic_ax.plot(t, np.sin(t + time.time()))**函數,但是這個和我想得實時畫圖不太一樣,在項目中要根據生成的數據實時繪圖,因此x軸的元素和y軸的元素個數是逐漸增加的。
通過閱讀上述 _update_canvas 函數代碼以及 dynamic_canvas.new_timer 可以使得每次調用_update_canvas是的相應的x的元素和y軸的元素增加更改后的代碼如下:
import sys
import time
import numpy as np
from matplotlib.backends.qt_compat import QtCore, QtWidgets, is_pyqt5
if is_pyqt5():
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
else:
from matplotlib.backends.backend_qt4agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(static_canvas)
self.addToolBar(NavigationToolbar(static_canvas, self))
dynamic_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(dynamic_canvas)
self.addToolBar(QtCore.Qt.BottomToolBarArea,
NavigationToolbar(dynamic_canvas, self))
self._static_ax = static_canvas.figure.subplots()
t = np.linspace(0, 10, 501)
self._static_ax.plot(t, np.tan(t), ".")
self.x = [] #建立空的x軸數組和y軸數組
self.y = []
self.n = 0
self._dynamic_ax = dynamic_canvas.figure.subplots()
self._timer = dynamic_canvas.new_timer(
100, [(self._update_canvas, (), {})])
self._timer.start()
def _update_canvas(self):
self.n += 1
if self.n == 200: #畫200個點就停止,根據實際情況確定終止條件
self._timer.stop()
self._dynamic_ax.clear()
self.x.append(np.pi/100*self.n) #x加入一個值,后一個值比前一個大pi/100
xx = np.array(self.x)
# t = np.linspace(0, 10, 101)
# Shift the sinusoid as a function of time.
self._dynamic_ax.plot(xx, np.sin(xx))
self._dynamic_ax.set_xlim(0,7)
self._dynamic_ax.set_ylim(-1,1)
self._dynamic_ax.figure.canvas.draw()
if __name__ == "__main__":
qapp = QtWidgets.QApplication(sys.argv)
app = ApplicationWindow()
app.show()
qapp.exec_()

上面的圖仍然靜止,下面的可以實時顯示

補充:pyqtgraph實時繪圖出現(xiàn)無法刷新問題
pyqtgraph實時繪圖時,會概率出現(xiàn)無法實時刷新繪制圖,原因是
while True: ...... update() # 通過 plotitem.setData()更新數據 ......
這里使用的是while循環(huán),不斷的更新數據概率出現(xiàn)繪圖不刷新和操作不響應(最小化操作會高概率出現(xiàn)該問題)
解決方法1:
我使用的是PlotWidget,remove后再addwidget,然后再重新繪制
解決方法2:
不使用while循環(huán),使用QTime定時器
t = QTimer() t.timeout.connect(self.update) t.start(10)
兩種方法都可以解決這個問題,推薦方法2
據說使用while循環(huán),需要在更新數據之后調用pg.QtGui.QApplication.processEvents()才能確保正常,這個本人試了不行,可能是我這邊的原因吧
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關文章
django-rest-framework 自定義swagger過程詳解
這篇文章主要介紹了django-rest-framework 自定義swagger過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-07-07
Python JSON格式數據的提取和保存的實現(xiàn)
這篇文章主要介紹了Python JSON格式數據的提取和保存的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-03-03
Python?sklearn?中的?make_blobs()?函數示例詳解
make_blobs()?是?sklearn.datasets中的一個函數,這篇文章主要介紹了Python?sklearn?中的?make_blobs()?函數,本文結合實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-02-02
Python threading.local代碼實例及原理解析
這篇文章主要介紹了Python threading.local代碼實例及原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03
python學習筆記之調用eval函數出現(xiàn)invalid syntax錯誤問題
python是一門多種用途的編程語言,時常扮演腳本語言的角色。一般來說,python可以定義為面向對象的腳本語言,這個定義把面向對象的支持和面向腳本語言的角色融合在一起。很多時候,人們常常喜歡用“腳本”和不是語言來描述python的代碼文件。2015-10-10

