Pyqt+matplotlib 實現(xiàn)實時畫圖案例
需求分析:
項目中根據(jù)測得的數(shù)據(jù)在界面上實時繪制
運行環(huán)境:
Python 3.7 + Matplotlib 3.0.2 + PyQt 5
matplot官網(wǎng)給的相應的例子:
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()))**函數(shù),但是這個和我想得實時畫圖不太一樣,在項目中要根據(jù)生成的數(shù)據(jù)實時繪圖,因此x軸的元素和y軸的元素個數(shù)是逐漸增加的。
通過閱讀上述 _update_canvas 函數(shù)代碼以及 dynamic_canvas.new_timer 可以使得每次調(diào)用_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軸數(shù)組和y軸數(shù)組 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個點就停止,根據(jù)實際情況確定終止條件 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()更新數(shù)據(jù) ......
這里使用的是while循環(huán),不斷的更新數(shù)據(jù)概率出現(xiàn)繪圖不刷新和操作不響應(最小化操作會高概率出現(xiàn)該問題)
解決方法1:
我使用的是PlotWidget,remove后再addwidget,然后再重新繪制
解決方法2:
不使用while循環(huán),使用QTime定時器
t = QTimer() t.timeout.connect(self.update) t.start(10)
兩種方法都可以解決這個問題,推薦方法2
據(jù)說使用while循環(huán),需要在更新數(shù)據(jù)之后調(diào)用pg.QtGui.QApplication.processEvents()才能確保正常,這個本人試了不行,可能是我這邊的原因吧
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關文章
Python aiohttp百萬并發(fā)極限測試實例分析
這篇文章主要介紹了Python aiohttp百萬并發(fā)極限測試,結(jié)合實例形式分析了Python異步編程基于aiohttp客戶端高并發(fā)請求的相關操作技巧與使用注意事項,需要的朋友可以參考下2019-10-10為Python的Tornado框架配置使用Jinja2模板引擎的方法
Jinja2是人氣Web框架Flask中的內(nèi)置模板引擎,而且與Django的模板引擎比較類似,這里我們就來看一下為Python的Tornado框架配置使用Jinja2模板引擎的方法2016-06-06tensorflow dataset.shuffle、dataset.batch、dataset.repeat順序區(qū)別詳
這篇文章主要介紹了tensorflow dataset.shuffle、dataset.batch、dataset.repeat順序區(qū)別詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2020-06-06