您的位置:首页技术文章
文章详情页

Python3.x+pyqtgraph实现数据可视化教程

浏览:28日期:2022-08-02 11:03:59

1、pyqtgraph库数据可视化效果还不错,特别是窗体程序中图像交互性较好;安装也很方便,用 pip 安装。

2、在Python中新建一个 .py 文件,然后写入如下代码并执行可以得到官方提供的很多案例(含代码),出现如下界面图像:

import pyqtgraph.examplespyqtgraph.examples.run()

Python3.x+pyqtgraph实现数据可视化教程

图1

Python3.x+pyqtgraph实现数据可视化教程

图2

Python3.x+pyqtgraph实现数据可视化教程

图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 npimport pyqtgraph as pgfrom pyqtgraph.Qt import QtGui, QtCore # 如下2行代码是我自己加入的,目的是修改默认的黑色背景为其它颜色背景pg.setConfigOption(’background’, ’w’)pg.setConfigOption(’foreground’, ’k’) from pyqtgraph.Point import Point #generate layoutapp = 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 0data1 = 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 hairvLine = 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.vbdef 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 sysimport cgitbfrom 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, QRectfrom 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() h1_wlayout = QHBoxLayout() h2_wlayout = QHBoxLayout() h3_wlayout = QHBoxLayout() v4_wlayout = QVBoxLayout() v5_wlayout = QVBoxLayout() self.statusBar().showMessage('状态栏') # 第一层 self._frist_story(h1_wlayout) # 第二层 self._second_story(h2_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(h1_wlayout) wlayout.addSpacing(10) # 增加布局间距 wlayout.addLayout(h2_wlayout) wlayout.addSpacing(10) # 增加布局间距 wlayout.addWidget(splt) wlayout.addLayout(h3_wlayout) wlayout.addWidget(self.statusBar()) h3_wlayout.addLayout(v4_wlayout, 0) h3_wlayout.addWidget(splt2) h3_wlayout.addLayout(v5_wlayout, 2) #wlayout.setAlignment(Qt.AlignTop) wwg.setLayout(wlayout) self.setCentralWidget(wwg) def _frist_story(self, h1_wlayout): # 第一层布局 self.h1_combox1 = QComboBox(minimumWidth=100) self.h1_combox1.addItems(wind_field) self.h1_combox2 = QComboBox(minimumWidth=100) self.h1_combox2.addItems(wind_mach_chooice(self.h1_combox1.currentText())) self.h1_combox3 = QComboBox(minimumWidth=100) self.h1_combox3.addItems(wind_blade) self.h1_combox4 = QComboBox(minimumWidth=100) self.h1_combox4.addItems(signal_type) # 行为测试 暂时无法使用 h1_cb1_action = QAction('风场选择', self) h1_cb1_action.setStatusTip('请选择风场') self.h1_combox1.addAction(h1_cb1_action) h1_wlayout.addItem(QSpacerItem(20, 20)) h1_wlayout.addWidget(QLabel('风场'),0) h1_wlayout.addWidget(self.h1_combox1,0) h1_wlayout.addItem(QSpacerItem(40, 20)) h1_wlayout.addWidget(QLabel('风机'), 0) h1_wlayout.addWidget(self.h1_combox2, 0) h1_wlayout.addItem(QSpacerItem(40, 20)) h1_wlayout.addWidget(QLabel('叶片ID'), 0) h1_wlayout.addWidget(self.h1_combox3, 0) h1_wlayout.addItem(QSpacerItem(40, 20)) h1_wlayout.addWidget(QLabel('信号类型'), 0) h1_wlayout.addWidget(self.h1_combox4, 0) h1_wlayout.setAlignment(Qt.AlignLeft) # 事件绑定 self.h1_combox1.currentIndexChanged.connect(self._wind_chooice) def _second_story(self, h2_wlayout): # 第二层布局 self.h2_date1 = QDateEdit(QDate.currentDate()) self.h2_date1.setCalendarPopup(True) self.h2_date2 = QDateEdit(QDate.currentDate()) self.h2_date2.setCalendarPopup(True) self.h2_button = QPushButton('运行') self.h2_button2 = QPushButton('停止') h2_wlayout.addItem(QSpacerItem(20, 20)) h2_wlayout.addWidget(QLabel('起始'),0) h2_wlayout.addWidget(self.h2_date1) h2_wlayout.addItem(QSpacerItem(50, 20)) h2_wlayout.addWidget(QLabel('结束'), 0) h2_wlayout.addWidget(self.h2_date2) h2_wlayout.addItem(QSpacerItem(70, 20)) h2_wlayout.addWidget(self.h2_button) h2_wlayout.addWidget(self.h2_button2) h2_wlayout.setAlignment(Qt.AlignLeft) # 事件绑定 self.h2_button.clicked.connect(lambda: self._start_func()) self.h2_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.h1_combox1.currentText()) self.h1_combox2.clear() self.h1_combox2.addItems(tmp_list) def _start_func(self): a = self.h1_combox1.currentText() b = self.h1_combox2.currentText() c = self.h1_combox3.currentText() d = self.h1_combox4.currentText() e = self.h2_date1.dateTime().toString('yy-MM-dd') f = self.h2_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 pgfrom TmpData import _read_data, wind_mach_chooicecolour = ['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 mydictdef plt_init():# 绘图初始化 pg.setConfigOption('background', 'w') plt = pg.PlotWidget() plt.addLegend(size=(150, 80)) plt.showGrid(x=True, y=True, alpha=0.5) return pltdef 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 pltif __name__ == ’__main__’: _data_to_dict() pass

模拟给其它文件传指定数据

# TmpData.py 文件名import osimport numpy as npfile_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, pyqtSignalclass 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')

这些天本人身体不舒服,但还是把做完的这个分享出来,有些细节没有具体说明,下次身体好点,再单独拿出来分享,累了,晚安!

以上这篇Python3.x+pyqtgraph实现数据可视化教程就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持好吧啦网。

标签: Python 编程
相关文章: