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
猜你喜欢
- 我们可用一个函数来实现小数转分数,不过只能转换能够整除的分数:Public Function XtoF(str 
- 1.检查重复元素下面的方法可以检查给定列表中是否有重复的元素。它使用了 set() 属性,该属性将会从列表中删除重复的元素。def all_
- 我在一篇文章所说,首页的“站点名称”最好用h1标签来定义,但从美观考虑,要用logo图片来代替h1,这时需要隐藏h1内的这段文字,但又不能对
- Django中每一个模型model都对应于数据库中的一张表,每个模型中的字段都对应于数据库表的列。方便的是,django可以自动生成这些cr
- 原来看到这个代码的时候,觉得功能不错,调试并整理了一下也许大家用的到,对于越来越注重用户体验的今天,这种功能一定很受欢迎,当然本例子只是一个
- 国外的空间和我们国内的空间使用的语言系统一般不一样,所以在网页程序上时如果处理不当很容易出现乱码,看了让人摸不着头脑。所以我们在编写程序时就
- Python图片处理模块PIL(pillow)pywin32的主要作用1.捕获窗口;2.模拟鼠标键盘动作;3.自动获取某路径下文件列表;4.
- 运行下面的代码你就可以清楚的认识到这两个参数的用法,innerText只能动态的改变指定元素内的文本内容,而innerHTML则不仅仅可以改
- 论坛经常有人会问到用CSS如何美化Select标签,其实但凡你看到很酷的都是用javascript来实现的。昨天试着做了一下,基本实现的初级
- 在研究ezSQL的时候就看到了mssql_connect()等一些php提供的连接MSSQL的函数,本以为php这个开源的风靡世界的编程语言
- 布尔类型是PHP中 最简单的类型。它的值可以为 TRUE 或 FALSE。如:$foo=false;$foo1=true;echo &quo
- 人的大脑通过双眼来辨别视觉图形获取信息。大脑根据储存的经验,将所看到的视觉图形建立起优先级。由此可见,一个良好的视觉设计可以帮助大脑迅速有效
- 一、简介 多线程编程技术可以实现代码并行性,优化处理能力,同时功能的
- 优秀的Stoyan Stefanov在他的新书中(《Javascript Patterns》)介绍了很多编写高质量代码的技巧,比如避免使用全
- 前言在《Python中if语句的使用方法》中提到,对于一种可能性、两种可能性或者多种可能性的情况,可以通过if语句来实现。而用if语句实现多
- 现将几种主要情况进行小结: 一、如何输入NULL值 如果不输入null值,当时间为空时,会默认写入"1900-01-01"
- HTTP暴力破解、撞库,有一些惯用的技巧,比如:1. 在扫号人人网时,我遇到单个账号错误两次,强制要求输入验证码,而对方并未实施IP策略。我
- JavaScript图片水平翻转后垂直翻反转的特效一:<!--把下列代码加到body区域内--><SCRIPT langu
- 数据库连接字符串的常见问题和解决方法:基本知识1:SQL Server数据库的身份验证方式,分windows验证,SQL Server验证两
- 这个网页颜色表是很好用,鼠标点击颜色即可复制颜色值到剪贴板,方便大家设计取色。下载苏昱css2 样式表中文手册包括颜色表:W3C- 十六色色