在之前介紹PyQtGraph的文章中,我們都是一次性的擷取資料并将其繪制為圖形。然而在很多場景中,我們都需要對實時的資料進行圖形化展示。
比如:
- 股票的實時行情
- 儀器裝置的實時狀态等
這時候就需要對資料進行實時的更新和繪制。今天我們就來介紹一下在PyQtGraph中根據實時資料更新繪制圖形。
今天的例子我們通過編寫一個電腦CPU實時使用率助手來講解。
一、通過Python擷取實時的CPU資訊
在Windows作業系統的電腦上,我們通過“任務管理器”可以很友善地檢視到自己電腦CPU實時的使用情況,并且CPU的占用率還會通過一個實時的圖形區域顯示出來,如下圖所示:

通過實時變化的CPU使用率圖形,我們可以清晰地看到CPU使用情況的變化。在Python中,我們也能很友善的擷取到計算機CPU的實時使用率。
# coding:utf-8# @檔案: 1.py# @建立者:州的先生# #日期:2019/5/12# 部落格位址:https://zmister.comimport psutilcpu = "CPU:%0.2f" % psutil.cpu_percent(interval=1) + "%"print(cpu)
複制
通過運作上述代碼,我們就能擷取到此時電腦CPU的使用率。通過将其改進一下,加入循環和時間間隔,我們就可以持續獲得目前電腦CPU的使用率,如下代碼所示:
# coding:utf-8# @檔案: 1.py# @建立者:州的先生# #日期:2019/5/12# 部落格位址:zmister.comimport psutilimport timedef get_cpu_info(): cpu = "CPU:%0.2f" % psutil.cpu_percent(interval=1) + "%" return cpudef main(): while True: info = get_cpu_info() print(info) time.sleep(1)if __name__ == "__main__": main()
複制
運作上述代碼,我們将每隔1秒擷取到實時的CPU使用率資料,這将是我們圖形界面程式的資料來源。
二、使用PyQt5建立一個圖形界面
有了資料來源之後,我們來建立一個圖形界面,這個圖形界面由一個Widget包裹着一個Plotwidget,圖形界面的核心就是一個ptqtgraph的圖形部件。其代碼如下所示:
# coding:utf-8# @檔案: 1.py# @建立者:州的先生# #日期:2019/5/12# 部落格位址:zmister.comfrom PyQt5 import QtWidgets,QtCore,QtGuiimport tushare as tsimport pyqtgraph as pgimport sysimport datetimeimport tracebackimport numpy as npclass MainUi(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("CPU使用率監控 - 州的先生https://zmister.com") self.main_widget = QtWidgets.QWidget() # 建立一個主部件 self.main_layout = QtWidgets.QGridLayout() # 建立一個網格布局 self.main_widget.setLayout(self.main_layout) # 設定主部件的布局為網格 self.setCentralWidget(self.main_widget) # 設定視窗預設部件 self.plot_widget = QtWidgets.QWidget() # 執行個體化一個widget部件作為K線圖部件 self.plot_layout = QtWidgets.QGridLayout() # 執行個體化一個網格布局層 self.plot_widget.setLayout(self.plot_layout) # 設定線圖部件的布局層 self.plot_plt = pg.PlotWidget() # 執行個體化一個繪圖部件 self.plot_plt.showGrid(x=True,y=True) # 顯示圖形網格 self.plot_layout.addWidget(self.plot_plt) # 添加繪圖部件到線圖部件的網格布局層 # 将上述部件添加到布局層中 self.main_layout.addWidget(self.plot_widget, 1, 0, 3, 3) self.setCentralWidget(self.main_widget)def main(): app = QtWidgets.QApplication(sys.argv) gui = MainUi() gui.show() sys.exit(app.exec_())if __name__ == '__main__': main()
複制
運作上述代碼,我們将會得到一個如下圖所示的圖形界面:
我們的CPU使用率資料将會通過圖形界面中間的畫布部件顯示出來。
三、在PyQtGraph中實時顯示CPU資料
建立好了基礎的圖形界面之後,我們就可以實時擷取電腦CPU的使用率然後将其繪制在圖形界面上了。
在之前的文章中,我們知道pyqtgraph的繪圖資料主要是通過setData()這個方法來轉化為圖形。我們可以設定一個定時器,每隔一個時間重新調用setData()方法對圖形資料進行設定,就能夠實作實時的資料可視化呈現。下面我們通過代碼示範一下:
from PyQt5 import QtWidgets,QtCore,QtGuiimport pyqtgraph as pgimport sysimport tracebackimport psutilclass MainUi(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("CPU使用率監控 - 州的先生https://zmister.com") self.main_widget = QtWidgets.QWidget() # 建立一個主部件 self.main_layout = QtWidgets.QGridLayout() # 建立一個網格布局 self.main_widget.setLayout(self.main_layout) # 設定主部件的布局為網格 self.setCentralWidget(self.main_widget) # 設定視窗預設部件 self.plot_widget = QtWidgets.QWidget() # 執行個體化一個widget部件作為K線圖部件 self.plot_layout = QtWidgets.QGridLayout() # 執行個體化一個網格布局層 self.plot_widget.setLayout(self.plot_layout) # 設定K線圖部件的布局層 self.plot_plt = pg.PlotWidget() # 執行個體化一個繪圖部件 self.plot_plt.showGrid(x=True,y=True) # 顯示圖形網格 self.plot_layout.addWidget(self.plot_plt) # 添加繪圖部件到K線圖部件的網格布局層 # 将上述部件添加到布局層中 self.main_layout.addWidget(self.plot_widget, 1, 0, 3, 3) self.setCentralWidget(self.main_widget) self.plot_plt.setYRange(max=100,min=0) self.data_list = [] self.timer_start() # 啟動定時器 時間間隔秒 def timer_start(self): self.timer = QtCore.QTimer(self) self.timer.timeout.connect(self.get_cpu_info) self.timer.start(1000) # 擷取CPU使用率 def get_cpu_info(self): try: cpu = "%0.2f" % psutil.cpu_percent(interval=1) self.data_list.append(float(cpu)) print(float(cpu)) self.plot_plt.plot().setData(self.data_list,pen='g') except Exception as e: print(traceback.print_exc())def main(): app = QtWidgets.QApplication(sys.argv) gui = MainUi() gui.show() sys.exit(app.exec_())if __name__ == '__main__': main()
複制
在上述代碼中,我們定義了一個1秒鐘的計時器,然後定義了一個資料清單data_list,擷取到的cpu使用率都将添加到這個清單中,然後作為圖形資料傳遞給pyqtgraph。
運作上述代碼,我們可以得到如下動圖所示的實時更新圖形界面,每一秒擷取到的CPU使用率資料都實時繪制為了線條:
由于所有的操作都是在主線程上進行的,會導緻圖形界面有些許的卡頓,更加理想的做法是建立一個子線程來生成和繪制圖形,在此就不作額外的示範了,大家可以自己嘗試一下。