您好,登錄后才能下訂單哦!
小編給大家分享一下Python3.x+pyqtgraph實現數據可視化的方法,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
1、pyqtgraph庫數據可視化效果還不錯,特別是窗體程序中圖像交互性較好;安裝也很方便,用 pip 安裝。
2、在Python中新建一個 .py 文件,然后寫入如下代碼并執行可以得到官方提供的很多案例(含代碼),出現如下界面圖像:
import pyqtgraph.examples
pyqtgraph.examples.run()
圖1
圖2
圖3
4、程序默認是黑色背景,這個是可以修改的。比如,在程序的開頭部分寫入如下代碼就可以修改背景:
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
更多說明,見 pyqtgraph 官網:http://www.pyqtgraph.org/documentation/style.html,“Line, Fill, and Color”部分的“Default Background and Foreground Colors”部分。
5、一個修改背景顏色的完整案例如下,可以直接運行程序:
import numpy as np import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtCore # 如下2行代碼是我自己加入的,目的是修改默認的黑色背景為其它顏色背景 pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') from pyqtgraph.Point import Point #generate layout app = QtGui.QApplication([]) win = pg.GraphicsWindow() win.setWindowTitle('pyqtgraph example: crosshair') label = pg.LabelItem(justify='right') win.addItem(label) p1 = win.addPlot(row=1, col=0) p2 = win.addPlot(row=2, col=0) region = pg.LinearRegionItem() region.setZValue(10) # Add the LinearRegionItem to the ViewBox, but tell the ViewBox to exclude this # item when doing auto-range calculations. p2.addItem(region, ignoreBounds=True) #pg.dbg() p1.setAutoVisible(y=True) #create numpy arrays #make the numbers large to show that the xrange shows data from 10000 to all the way 0 data1 = 10000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000) data2 = 15000 + 15000 * pg.gaussianFilter(np.random.random(size=10000), 10) + 3000 * np.random.random(size=10000) p1.plot(data1, pen="r") p1.plot(data2, pen="g") p2.plot(data1, pen="w") def update(): region.setZValue(10) minX, maxX = region.getRegion() p1.setXRange(minX, maxX, padding=0) region.sigRegionChanged.connect(update) def updateRegion(window, viewRange): rgn = viewRange[0] region.setRegion(rgn) p1.sigRangeChanged.connect(updateRegion) region.setRegion([1000, 2000]) #cross hair vLine = pg.InfiniteLine(angle=90, movable=False) hLine = pg.InfiniteLine(angle=0, movable=False) p1.addItem(vLine, ignoreBounds=True) p1.addItem(hLine, ignoreBounds=True) vb = p1.vb def mouseMoved(evt): pos = evt[0] ## using signal proxy turns original arguments into a tuple if p1.sceneBoundingRect().contains(pos): mousePoint = vb.mapSceneToView(pos) index = int(mousePoint.x()) if index > 0 and index < len(data1): label.setText("<span style='font-size: 12pt'>x=%0.1f, <span style='color: red'>y1=%0.1f</span>, <span style='color: green'>y2=%0.1f</span>" % (mousePoint.x(), data1[index], data2[index])) vLine.setPos(mousePoint.x()) hLine.setPos(mousePoint.y()) proxy = pg.SignalProxy(p1.scene().sigMouseMoved, rateLimit=60, slot=mouseMoved) #p1.scene().sigMouseMoved.connect(mouseMoved) ## Start Qt event loop unless running in interactive mode or using pyside. if __name__ == '__main__': import sys if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_()
知識補充:python圖形化實例分享--pyqt5與pyqtgraph嵌入繪圖
序言
之前也寫過一些圖形化界面的程序,基本上都是用wxPython寫的,確實簡單粗暴易上手。這次的任務是要寫一個繪圖的程序,wx模塊就顯得不太友好了,我就去網上找了一些資料,發現PyQtGraph畫這種K線圖、波形圖等圖形真是太簡單了,更多的關于wx、qt等模塊的細節學習可以看我后面的參考資料,我這里就分享一下我本程序的心得,和對有些方法使用上自己的理解
項目開始
引用頭文件
pyqt5_draw_1 這是主程序文件,負責主窗口圖形化界面
import sys # 與PyQt5配合使用 from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout, QHBoxLayout, QVBoxLayout,QLabel, QComboBox,QPushButton, QDateEdit, QSpacerItem,QFrame, QSizePolicy, QSplitter, QRadioButton, QGroupBox,QCheckBox,QLineEdit, QAction) # 上面是QT圖形化要引用的所有包 from PyQt5.QtCore import Qt, QDate, QRect # 對齊、時間等 from PyQt5.QtCore import QThread, pyqtSignal # 多線程管理 import pyqtgraph as pg # 繪圖包 from Tmp_Data import * # 自定義文件,下面有介紹 from Mythreading import * # 自定義文件,下面有介紹 from pyqt5_graph import * # 自定義文件,下面有介紹
如果PyQt5、pyqtgraph未安裝的,最簡單的安裝方式就用python自帶的pip工具安裝,如果沒有pip的或不會安裝可直接百度
c:\> pip install PyQt5 pyqtgraph
圖形化主界面搭建
# pyqt5_draw_1.py 文件名 import sys import cgitb from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout, QHBoxLayout, QVBoxLayout,QLabel, QComboBox,QPushButton, QDateEdit, QSpacerItem,QFrame, QSizePolicy, QSplitter, QRadioButton, QGroupBox,QCheckBox,QLineEdit, QAction) from PyQt5.QtCore import Qt, QDate, QRect from TmpData import * from Mythreading import * from pyqt5_graph import * class Qt_Test_Frame(QMainWindow): Items = [] def __init__(self): #super(Qt_Test_Frame, self).__init__(*args, **kw) super().__init__() # 初始化界面 self._initUI() self.show() def _initUI(self): self.setWindowTitle("QT圖形界面測試") self.resize(800, 600) wwg = QWidget() # 全局布局 wlayout = QVBoxLayout() h2_wlayout = QHBoxLayout() h3_wlayout = QHBoxLayout() h4_wlayout = QHBoxLayout() v4_wlayout = QVBoxLayout() v5_wlayout = QVBoxLayout() self.statusBar().showMessage("狀態欄") # 第一層 self._frist_story(h2_wlayout) # 第二層 self._second_story(h3_wlayout) # 第三層 左 self._third_left(v4_wlayout, v5_wlayout) # 第三層 右 self._fouth_right(v5_wlayout) # 加載 splt = self._my_line() splt2 = self._my_line(False) wlayout.addSpacing(10) # 增加布局間距 wlayout.addLayout(h2_wlayout) wlayout.addSpacing(10) # 增加布局間距 wlayout.addLayout(h3_wlayout) wlayout.addSpacing(10) # 增加布局間距 wlayout.addWidget(splt) wlayout.addLayout(h4_wlayout) wlayout.addWidget(self.statusBar()) h4_wlayout.addLayout(v4_wlayout, 0) h4_wlayout.addWidget(splt2) h4_wlayout.addLayout(v5_wlayout, 2) #wlayout.setAlignment(Qt.AlignTop) wwg.setLayout(wlayout) self.setCentralWidget(wwg) def _frist_story(self, h2_wlayout): # 第一層布局 self.h2_combox1 = QComboBox(minimumWidth=100) self.h2_combox1.addItems(wind_field) self.h2_combox2 = QComboBox(minimumWidth=100) self.h2_combox2.addItems(wind_mach_chooice(self.h2_combox1.currentText())) self.h2_combox3 = QComboBox(minimumWidth=100) self.h2_combox3.addItems(wind_blade) self.h2_combox4 = QComboBox(minimumWidth=100) self.h2_combox4.addItems(signal_type) # 行為測試 暫時無法使用 h2_cb1_action = QAction("風場選擇", self) h2_cb1_action.setStatusTip("請選擇風場") self.h2_combox1.addAction(h2_cb1_action) h2_wlayout.addItem(QSpacerItem(20, 20)) h2_wlayout.addWidget(QLabel("風場"),0) h2_wlayout.addWidget(self.h2_combox1,0) h2_wlayout.addItem(QSpacerItem(40, 20)) h2_wlayout.addWidget(QLabel("風機"), 0) h2_wlayout.addWidget(self.h2_combox2, 0) h2_wlayout.addItem(QSpacerItem(40, 20)) h2_wlayout.addWidget(QLabel("葉片ID"), 0) h2_wlayout.addWidget(self.h2_combox3, 0) h2_wlayout.addItem(QSpacerItem(40, 20)) h2_wlayout.addWidget(QLabel("信號類型"), 0) h2_wlayout.addWidget(self.h2_combox4, 0) h2_wlayout.setAlignment(Qt.AlignLeft) # 事件綁定 self.h2_combox1.currentIndexChanged.connect(self._wind_chooice) def _second_story(self, h3_wlayout): # 第二層布局 self.h3_date1 = QDateEdit(QDate.currentDate()) self.h3_date1.setCalendarPopup(True) self.h3_date2 = QDateEdit(QDate.currentDate()) self.h3_date2.setCalendarPopup(True) self.h3_button = QPushButton("運行") self.h3_button2 = QPushButton("停止") h3_wlayout.addItem(QSpacerItem(20, 20)) h3_wlayout.addWidget(QLabel("起始"),0) h3_wlayout.addWidget(self.h3_date1) h3_wlayout.addItem(QSpacerItem(50, 20)) h3_wlayout.addWidget(QLabel("結束"), 0) h3_wlayout.addWidget(self.h3_date2) h3_wlayout.addItem(QSpacerItem(70, 20)) h3_wlayout.addWidget(self.h3_button) h3_wlayout.addWidget(self.h3_button2) h3_wlayout.setAlignment(Qt.AlignLeft) # 事件綁定 self.h3_button.clicked.connect(lambda: self._start_func()) self.h3_button2.clicked.connect(lambda: self._stop_func()) def _third_left(self, v4_wlayout, v5_wlayout): # 第三層布局 # 分量布局 v4_group_imf = QGridLayout() vbox1 = QGroupBox("分量值") self.radio_1 = QRadioButton("分量1") self.radio_2 = QRadioButton("分量2") self.radio_3 = QRadioButton("分量3") self.radio_4 = QRadioButton("分量4") self.radio_5 = QRadioButton("分量5") self.radio_6 = QRadioButton("分量6") self.radio_7 = QRadioButton("分量7") self.radio_8 = QRadioButton("分量8") self.radio_9 = QRadioButton("分量9") self.radio_1.setChecked(True) self.radio_val = self.radio_1.text() # 優先級布局 v4_group_prior = QGridLayout() vbox2 = QGroupBox("優先級") cb1 = QCheckBox("葉片1") cb2 = QCheckBox("葉片2") cb3 = QCheckBox("葉片3") self.v4_lineEdit = QLineEdit() # 時間布局 v4_group_time = QGridLayout() vbox3 = QGroupBox("時間選擇") self.v4_combox1 = QComboBox(minimumWidth=100) self.v4_combox1.addItem("空") # 按鍵 v4_button = QPushButton("顯示圖形") # 寫入網格格布局 v4_group_imf.addWidget(self.radio_1, 0, 0) v4_group_imf.addWidget(self.radio_2, 0, 1) v4_group_imf.addWidget(self.radio_3, 1, 0) v4_group_imf.addWidget(self.radio_4, 1, 1) v4_group_imf.addWidget(self.radio_5, 2, 0) v4_group_imf.addWidget(self.radio_6, 2, 1) v4_group_imf.addWidget(self.radio_7, 3, 0) v4_group_imf.addWidget(self.radio_8, 3, 1) v4_group_imf.addWidget(self.radio_9, 4, 0) v4_group_prior.addWidget(cb1, 1, 0) v4_group_prior.addWidget(cb2, 2, 0) v4_group_prior.addWidget(cb3, 3, 0) v4_group_prior.addWidget(QLabel("選擇是:"),4,0) v4_group_prior.addWidget(self.v4_lineEdit, 5, 0) v4_group_time.addWidget(self.v4_combox1) # 寫入左側布局 vbox1.setLayout(v4_group_imf) vbox2.setLayout(v4_group_prior) vbox3.setLayout(v4_group_time) v4_wlayout.addItem(QSpacerItem(50, 20)) v4_wlayout.addWidget(vbox1) v4_wlayout.addItem(QSpacerItem(50, 20)) v4_wlayout.addWidget(vbox2) v4_wlayout.addItem(QSpacerItem(50, 20)) v4_wlayout.addWidget(vbox3) v4_wlayout.addItem(QSpacerItem(50, 20)) v4_wlayout.addWidget(v4_button) v4_wlayout.addItem(QSpacerItem(50, 20)) # 事件綁定 self.radio_1.toggled.connect(lambda: self._changestyle(self.radio_1)) self.radio_2.toggled.connect(lambda: self._changestyle(self.radio_2)) self.radio_3.toggled.connect(lambda: self._changestyle(self.radio_3)) self.radio_4.toggled.connect(lambda: self._changestyle(self.radio_4)) self.radio_5.toggled.connect(lambda: self._changestyle(self.radio_5)) self.radio_6.toggled.connect(lambda: self._changestyle(self.radio_6)) self.radio_7.toggled.connect(lambda: self._changestyle(self.radio_7)) self.radio_8.toggled.connect(lambda: self._changestyle(self.radio_8)) self.radio_9.toggled.connect(lambda: self._changestyle(self.radio_9)) cb1.stateChanged.connect(lambda: self._prior_func(cb1)) cb2.stateChanged.connect(lambda: self._prior_func(cb2)) cb3.stateChanged.connect(lambda: self._prior_func(cb3)) v4_button.clicked.connect(lambda: self._show_func(v5_wlayout)) def _fouth_right(self, v5_wlayout): # 加載波形圖 self.tmp_plt = plt_init() v5_wlayout.addWidget(self.tmp_plt) def _my_line(self, var=True): # var 為True時,為橫線,否則為豎線 line = QFrame(self) line_var = QFrame.HLine sp_var = Qt.Horizontal if not var: line_var = QFrame.VLine sp_var = Qt.Vertical line.setFrameShape(line_var) line.setFrameShadow(QFrame.Sunken) splitter = QSplitter(sp_var) splitter.addWidget(line) return splitter def _wind_chooice(self): tmp_list = wind_mach_chooice(self.h2_combox1.currentText()) self.h2_combox2.clear() self.h2_combox2.addItems(tmp_list) def _start_func(self): a = self.h2_combox1.currentText() b = self.h2_combox2.currentText() c = self.h2_combox3.currentText() d = self.h2_combox4.currentText() e = self.h3_date1.dateTime().toString("yy-MM-dd") f = self.h3_date2.dateTime().toString("yy-MM-dd") # 多線程的引用 self.start_func = RunThread(target=self._start_thread, args=(a, b, c, d, e, f)) # 多線程啟動 self.start_func.start() def _stop_func(self): # 線程停止 self.start_func.stop() print("運行結束") def _start_thread(self, a, b, c, d, e, f): print("*****運行打印*****") print(wind_mach_chooice(a)) print(a,b,c,d) print(e) print(f) print("%s" % (time.strftime('<%H:%M:%S>', time.localtime()))) self.v4_combox1.clear() self.v4_combox1.addItems(tmp_time_list) print("*****運行打印*****") def _changestyle(self, btn): # 單選項的判斷函數 if btn.isChecked(): self.radio_val = btn.text() #print("%s"%(time.strftime('<%H:%M:%S>', time.localtime()))) def _prior_func(self, cb): # 復選框內容添加 if cb.isChecked(): if cb.text()[-1] not in self.Items: self.Items.append(cb.text()[-1]) shop_cart= ",".join(self.Items) self.v4_lineEdit.setText(shop_cart) else: if cb.text()[-1] in self.Items: self.Items.remove(cb.text()[-1]) shop_cart = ",".join(self.Items) self.v4_lineEdit.setText(shop_cart) def _show_func(self, v5_wlayout): print("*****顯示打印*****") print(self.radio_val) num = self.v4_lineEdit.text() print(self.v4_combox1.currentText()) v5_wlayout.removeWidget(self.tmp_plt) self.tmp_plt = plt_show(num) v5_wlayout.addWidget(self.tmp_plt) print("*****顯示打印*****") if __name__ == '__main__': cgitb.enable(format="text") app = QApplication(sys.argv) win = Qt_Test_Frame() sys.exit(app.exec_())
處理把列表文件轉成字典與繪圖
# pyqt5_graph.py 文件名 import pyqtgraph as pg from TmpData import _read_data, wind_mach_chooice colour = ["r", "g", "b"] yp_list = ["葉片1", "葉片2", "葉片3"] def _data_to_dict(): mydict = {} for my_vars, i in zip(_read_data(), range(len(_read_data()))): tmp_dict = {} for var, j in zip(my_vars, range(len(my_vars))): tmp_dict[var[0]] =var[1] mydict[i] = tmp_dict return mydict def plt_init(): # 繪圖初始化 pg.setConfigOption("background", "w") plt = pg.PlotWidget() plt.addLegend(size=(150, 80)) plt.showGrid(x=True, y=True, alpha=0.5) return plt def plt_show(num): # 傳繪制的新圖 mydict = _data_to_dict() pg.setConfigOption("background", "w") plt = pg.PlotWidget() plt.addLegend(size=(150, 80)) plt.showGrid(x=True, y=True, alpha=0.5) for i in num.split(","): i = int(i)-1 plt.plot(x=list(mydict[i].keys()), y=list(mydict[i].values()), pen=colour[i], name=yp_list[i]) return plt if __name__ == '__main__': _data_to_dict() pass
模擬給其它文件傳指定數據
# TmpData.py 文件名 import os import numpy as np file_path = os.path.join(os.getcwd(), "風機采集信號數據\\") wind_field = ["風場1", "風場2", "風場3"] wind_machine = {"風場1":["大別山", "天目山"], "風場2":["昆侖山", "三清山"], "風場3":["五指山", "火焰山"]} wind_blade = ["X-20Hz", "X-1K", "Y-20Hz", "Y-1K"] signal_type = ["包絡", "振動"] tmp_time_list = ["20190501", "20190502", "20190504", "20190508", "20190515"] def wind_mach_chooice(val): return wind_machine[val] def _read_data(): file_list = os.listdir(file_path) file_list = [var for var in file_list if var.split(".")[1] == "csv"] a = [] for var in file_list: tmp = os.path.join(file_path, var) rd_file = np.loadtxt(tmp, delimiter=",", usecols=(0, 1)) a.append(rd_file) return a[0], a[1], a[2]
多線程管理
因為程序運行時間久,主界面就會出現假死的狀態,要引用多線程
# Mythreading.py 文件名 from PyQt5.QtCore import QThread, pyqtSignal class RunThread(QThread): counter_value = pyqtSignal(int) def __init__(self, target, args, name=""): QThread.__init__(self) self.target = target self.args = args self.is_running = True def run(self): #print("starting",self.name, "at:",ctime()) self.res = self.target(*self.args) def stop(self): # 負責停止線程 self.terminate()
關于QT異常直接退出沒有報錯的情況,查bug比較麻煩
import cgitb # 這句放在所有程序開始前,這樣就可以正常打印異常了 cgitb.enable(format="text")
1、簡單易用,與C/C++、Java、C# 等傳統語言相比,Python對代碼格式的要求沒有那么嚴格;2、Python屬于開源的,所有人都可以看到源代碼,并且可以被移植在許多平臺上使用;3、Python面向對象,能夠支持面向過程編程,也支持面向對象編程;4、Python是一種解釋性語言,Python寫的程序不需要編譯成二進制代碼,可以直接從源代碼運行程序;5、Python功能強大,擁有的模塊眾多,基本能夠實現所有的常見功能。
看完了這篇文章,相信你對“Python3.x+pyqtgraph實現數據可視化的方法”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。