Python3.x+pyqtgraph实现数据可视化教程
作者:higher80 发布时间:2023-09-25 23:24:47
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()
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 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")
这些天本人身体不舒服,但还是把做完的这个分享出来,有些细节没有具体说明,下次身体好点,再单独拿出来分享,累了,晚安!
来源:https://blog.csdn.net/higher80/article/details/80923054


猜你喜欢
- 利用PHP中的thinkphp5进行项目开发,将view一道项目跟目录下进入到/www/wwwroot/xxxx/application/c
- function ReportFileStatus(filespec) { var fso, s = filespec; fso = new
- 安装pip install requests发送网络请求import requestsr=requests.get('http://
- 1、sqldmo SQLDMO是操作SQLServer的理想的方式,如果您的数据库是SQLServer就可以考虑使用这种方式。在C#中使用S
- 一、SQLAlchemy 介绍1.1 ORM 的概念ORM全称Object Relational Mapping(对象关系映射),通过 OR
- 目录技术背景python对Excel表格的处理vaex的安装与使用vaex的安装性能对比数据格式转换总结概要技术背景数据处理是一个当下非常热
- 前言本文主要给大家介绍了关于Django快速分页的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。分页在web开发
- 最近在写测试平台,需要实现一个节点服务器的api,正好在用django,准备使用djangorestframework插件实现。需求实现一个
- 导读排序算法可以称得上是我的盲点, 曾几何时当我知道Chrome的Array.prototype.sort使用了快速排序时, 我的内心是奔溃
- 静态方法:将下面的代码复制到<body>~</body>内 程序代码 <table cellpadd
- 本文实例讲述了基于pako.js实现gzip的压缩和解压功能。分享给大家供大家参考,具体如下:<!DOCTYPE html>&l
- 这段时间告诉项目需要,用到了vue。刚开始搭框架的时候用的是vue-resource后面看到官方推荐axios就换过来了 顺便封装了一下 /
- 这篇文章主要介绍了基于Python批量生成指定尺寸缩略图代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 本文实例讲述了Python通过公共键对字典列表排序算法。分享给大家供大家参考,具体如下:问题:想根据一个或多个字典中的值来对列表排序解决方案
- 1、获取数据库标识符:DB_IDDB_ID函数用于获取当前数据库的唯一ID(int数据类型),数据库ID用于服务器上唯一区分书库。语法格式:
- frm文件和ibd文件简介 在MySQL中,如果我们使用了默认的存储引擎innodb创建一张表,那么在文件夹下面就会
- 多级联动下拉选择框,动态获取下一级,每一级数据为XML,可支持无限级(浏览器端需要Microsoft.XMLDOM支持)项目需要,一个材料类
- 1.每个客户端连接都会从服务器进程中分到一个属于它的线程。而该连接的相应查询都都会通过该线程处理。2.服务器会缓存线程。因此并不会为每个新连
- 最近用layer ui上传文件遇到了一个问题,我想在上传文件之前把data-id传入后台,layer文档找了一下也没有找到类似的说明,经过一
- 我们知道,任何数据库系统都无法避免崩溃的状况,即使你使用了Clustered,双机热备……仍然无