今週は、主に pyqtgraph から QCustomPlot2 への描画コントロールの移行を実現しました. 全体的な感じとしては、まず第一に、この描画コントロールは偉大なマスターの手によるものであり、品質はもちろんそうではありません. 「cpp の qt エコロジーは非常に人気があります。なぜなら、私はインターネットで python しか見つけられなかったからです。そうです、他はすべて cpp のバージョン コードです。python を使用する人はほとんどいませんが、偉大な神の輝きを隠すことはできません。.今週の移行プロセスのいくつかのバンプ, 最終的に, 以前にpyqtgraphに実装されたすべての機能が正常に実装されました. それはplot2に実装されました. 私は、このコントロールを使用して同じ機能を達成すると言わなければなりません, 実装コードはそうではありません減少しただけですが、問題はほとんどありません. 明らかなバグがあるpyqtgraphとは異なり、コントロール自体に基本的にバグは見つかりませんでした (もちろん、それは私の食べ物でもあるかもしれません) 同時に、pyqtgraphに現れたパフォーマンスの問題pyqtgraph で散布図を描くと、データが多すぎると非常に固まるのですが、折れ線グラフは非常に滑らかで、何が問題なのかわかりません ( # ただし、基本的にはQCustomPlot2) で散布図と折れ線グラフを描画する際のパフォーマンスに違いはありません. 訂正させてください. このコントロールの散布図もデータ量が多い場合, 特にトレーサーが移動する場合に問題があります. pyqtgraph と同じはずです. . openglにしか期待できないようですが、openglサポートを自分でコンパイルするのは少し面倒です. 後で見てみましょう, しかし、機能はまだかなり完璧です.
言うことはあまりありませんが、コードを入れてください:
from calendar import c
from datetime import timedelta
from hashlib import new
import sys
import json
import pickle
#import cgitb
import os
import time
import multiprocessing
from unicodedata import name
import numpy as np
from pandas._libs.tslibs.timestamps import Timestamp
from ctypes.wintypes import MSG
import random
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout,QTabWidget,
QHBoxLayout, QVBoxLayout,QLabel, QComboBox,QPushButton,
QDateEdit, QSpacerItem,QFrame, QSizePolicy, QSplitter,
QRadioButton, QGroupBox,QCheckBox,QLineEdit, QAction,
QFileDialog,QListView,QListWidget,QListWidgetItem,QMenu,
QProgressBar,QProgressDialog,QMessageBox,QAbstractItemView,
QSplashScreen)
from PyQt5.QtCore import Qt, QDate, QRect,QSize
from PyQt5 import QtCore
from PyQt5.QtGui import QIcon, QBitmap, QPainter, QPixmap, QCursor, QMovie,QLinearGradient
import pyqtgraph as pg
from pyqtgraph import mkPen,DateAxisItem,AxisItem
import QCustomPlot2 as qcp
from QCustomPlot2 import (QCustomPlot,QCP,QCPAxisRect,QCPAxis,QCPScatterStyle,QCPItemPosition,
QCPAxisTickerDateTime,QCPLineEnding,QCPItemTracer,QCPItemLine,QCPGraph,
QCPItemStraightLine)
from formated_axis import FormatedAxis
from DropListWidget import DropInList
from utils import *
from conf import *
from MyComboCheckBox import *
from DailyAnalysisDialog import *
from DurableAnalysisDialog import *
from FormatConversionDialog import *
from BleedDownAnalysisDialog import *
from PolarAnalysisDialog import *
from DropListWidget import *
from task_threads import *
from LittleWidgets import Cursor
import images
#from QCandyUi.CandyWindow import colorful
class MainWindow(QMainWindow):
def __init__(self,*args):
super().__init__()
self.time_index = []
self.ydata = [[],[]]
self.select_data = []
self.y_axis = ['sPDU_StkOut_iSTK_A','']
self.zdata = {}
self.all_signals = []
self.have_sig = ['Time']
self.tx = 0
self.ty = 0
self.plt_list = []
self.ax_list = []
self.plt_color_list = []
self.graph_list = []
self.line_style = 'line'
self.plt_gph_map = {}
self.draw_sig = []
self.axis_layout_list = []
self.x_col = 'index'
self.theme = "black"
self.color_map = color_map
self.mouse_ispressed = False
self.vline1 = None
self.conf_data = {}
self.merge_cols = []
self._init_ui()
self.show()
if len(args[0]) > 1:
self.f_list = args[0][1:]
self.load_data()
def _init_ui(self):
self.setWindowTitle('分析工具')
self.resize(1200,700)
self.setWindowIcon(QIcon(':/icon/数据分析.ico'))
qwg = QWidget()
left_wdgt = QWidget()
leftarea_layout = QVBoxLayout()
#全局布局
wlayout = QVBoxLayout()
#单线按钮
self.tool_bar = self.addToolBar("单线")
single_line = QAction(QIcon(':/icon/单线.png'), '单线', self)
self.tool_bar.addAction(single_line)
#双线按钮
multi_line = QAction(QIcon(':/icon/双线.png'), '双线', self)
self.tool_bar.addAction(multi_line)
self.multi_flag = False
#重置按钮
reset_button = QAction(QIcon(':/icon/reset.png'), '重置(F)', self)
reset_button.setShortcut(QKeySequence("f"))
self.tool_bar.addAction(reset_button)
#折线图按钮
line_button = QAction(QIcon(':/icon/折线图.ico'), '折线图', self)
line_button.setShortcut(QKeySequence("l"))
self.tool_bar.addAction(line_button)
#散点图按钮
scatter_button = QAction(QIcon(':/icon/散点图.ico'), '散点图', self)
scatter_button.setShortcut(QKeySequence("s"))
self.tool_bar.addAction(scatter_button)
#点线图按钮
ls_button = QAction(QIcon(':/icon/点线图.ico'), '点线图', self)
ls_button.setShortcut(QKeySequence("l+s"))
self.tool_bar.addAction(ls_button)
#导出按钮
export_button = QAction(QIcon(':/icon/导出.ico'), '导出', self)
#ls_button.setShortcut(QKeySequence("Ctrl + e"))
self.tool_bar.addAction(export_button)
#主题按钮
theme_button = QAction(QIcon(':/icon/主题.png'), '主题', self)
theme_button.setShortcut(QKeySequence("f"))
#self.tool_bar.addAction(theme_button)
#self.tool_bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.tool_bar.actionTriggered.connect(self.toolbtnpressed)
#wlayout.addWidget(self.tool_bar)
self.splitter = QSplitter(Qt.Horizontal)
self.search_box = QLineEdit()
self.search_box.textChanged.connect(self.search_sig)
self.leftarea = QTabWidget()
self.siglist = QListWidget()
self.siglist.setDragEnabled(True)
self.siglist.setAcceptDrops(True)
#self.siglist.setStyleSheet('QListWidget {border:none; }')
self.siglist.itemClicked.connect(self.item_clicked)
self.siglist.itemDoubleClicked.connect(self.push_to_select)
self.siglist.setContextMenuPolicy(Qt.CustomContextMenu)
self.siglist.customContextMenuRequested[QtCore.QPoint].connect(self.my_list_widget_context)
#选择信号列表
self.select_widget = QWidget()
v_layout = QVBoxLayout()
self.time_label = QLabel("time")
self.select_sig = DropInList()
self.select_sig.enter.connect(self.draw_chart_mul2)
self.select_sig.select_state.connect(self.select_state)
self.select_sig.itemClicked.connect(self.switch_sig)
self.select_sig.setContextMenuPolicy(Qt.CustomContextMenu)
self.select_sig.customContextMenuRequested[QtCore.QPoint].connect(self.select_sig_context)
#self.select_sig.setStyleSheet('QListWidget {border:none; }')
v_layout.addWidget(self.select_sig)
v_layout.addWidget(self.time_label)
#v_layout.setSpacing(5)
v_layout.setContentsMargins(0,0,5,0)
self.select_widget.setLayout(v_layout)
#self.select_sig.setAcceptDrops(Tr)
self.search_result = QListWidget()
self.search_result.setDragEnabled(True)
self.search_result.itemDoubleClicked.connect(self.push_to_select)
self.search_result.setContextMenuPolicy(Qt.CustomContextMenu)
self.search_result.customContextMenuRequested[QtCore.QPoint].connect(self.my_search_list_widget_context)
#self.search_result.setStyleSheet('QListWidget {border:none; }')
self.leftarea.addTab(self.siglist,'全部信号')
self.leftarea.addTab(self.search_result,'搜索结果')
leftarea_layout.addWidget(self.search_box)
leftarea_layout.addWidget(self.leftarea)
#leftarea_layout.setSpacing(5)
leftarea_layout.setContentsMargins(0,0,5,0)
left_wdgt.setLayout(leftarea_layout)
self.splitter.addWidget(left_wdgt)
self.splitter.addWidget(self.select_widget)
self.status_bar = self.statusBar()
self.status_bar.showMessage("状态栏")
splt = self._my_line()
#绘图
self.graphic_widget_init()
self.g_wdgt = QWidget()
print(self.win)
#self.g_wdgt.addItem(self.win)
self.pw = pg.GraphicsView()
self.pw.setCentralWidget(self.win)
#注意plt_init函数,必须放在self.pw.setCentralWidget(self.win)后面执行,否则self.pltwgt没有scene()方法返回None
self.line_plot = QCustomPlot()
self.plt_init()
self.splitter.addWidget(self.line_plot)
self.splitter.setStretchFactor(0, 0)
self.splitter.setStretchFactor(1, 0)
self.splitter.setStretchFactor(2, 1)
#第一层
self._zero_layer()
wlayout.addWidget(self.splitter)
wlayout.addWidget(self.status_bar)
self.qssfile = ":/style/style.qss"
self.qssstyle = read_qss(self.qssfile)
self.setStyleSheet(self.qssstyle)
qwg.setLayout(wlayout)
self.setCentralWidget(qwg)
def toolbtnpressed(self,tool):
print(tool.text())
tool_name = tool.text()
if tool_name == "双线":
if not self.multi_flag:
self.multi_flag = True
self.vline1 = QCPItemStraightLine(self.line_plot)
self.vline1.setLayer("overlay")
linesPen = QPen(QColor("#FFFF00"),1,Qt.PenStyle.SolidLine)
lineSelectedPen = QPen(QColor("#ffffff"),1,Qt.PenStyle.SolidLine)
self.vline1.setPen(linesPen)
self.vline1.setSelectedPen(lineSelectedPen)
self.vline1.setClipToAxisRect(True)
self.vline1.point1.setTypeX(QCPItemPosition.ptPlotCoords)
self.vline1.point1.setTypeY(QCPItemPosition.ptPlotCoords)
self.vline1.point2.setTypeX(QCPItemPosition.ptPlotCoords)
self.vline1.point2.setTypeY(QCPItemPosition.ptPlotCoords)
self.vline1.setVisible(True)
self.vline1.setSelectable(True)
self.vline1.selectionChanged.connect(self.line1_selection_changed)
print(self.x)
self.vline1.point1.setCoords(self.x1 +self.x1*0.5 , 100)
self.vline1.point2.setCoords(self.x1 +self.x1*0.5, 0)
else:
self.multi_flag = False
self.line_plot.removeItem(self.vline1)
self.vline1 = None
self.line_plot.replot()
if tool_name == "重置(F)":
self.reset_plt()
if tool_name == "主题":
self.switch_theme()
if tool_name == "散点图":
self.line_style = 'scatter'
self.set_line_style('scatter')
if tool_name == "折线图":
self.line_style = 'line'
self.set_line_style('line')
if tool_name == "点线图":
self.line_style = 'ls'
self.set_line_style('ls')
if tool_name == "导出":
filepath, ftype = QFileDialog.getSaveFileName(self, '文件保存', '/', '.png;;.pdf;;.jpg')
print(ftype)
if ftype == '.png':
if not filepath.endswith('.png'):
filepath += ftype
self.line_plot.savePng(filepath,self.line_plot.width(),self.line_plot.height())
if ftype == '.jpg':
if not filepath.endswith('.jpg'):
filepath += ftype
self.line_plot.saveJpg(filepath,self.line_plot.width(),self.line_plot.height())
if ftype == '.pdf':
if not filepath.endswith('.pdf'):
filepath += ftype
self.line_plot.savePdf(filepath,self.line_plot.width(),self.line_plot.height())
show_message(self,"info","导出成功 ")
def graph_selection_changed(self,res,idx,evt):
print(res,evt)
print(self.ax_list)
self.graph = res
for ax in self.ax_list:
ax.setVisible(False)
self.plt_gph_map[res].setVisible(True)
self.qcp_rect.setRangeDragAxes([self.x_axis,self.plt_gph_map[res]])
self.qcp_rect.setRangeZoomAxes([self.x_axis,self.plt_gph_map[res]])
self.line_plot.replot()
print("============after change============")
def switch_theme(self):
print("=======self.theme=======",self.theme)
if self.theme == "black":
pg.setConfigOption("background", "white")
self.theme = "white"
else:
pg.setConfigOption("background", "black")
self.theme = "black"
def item_clicked(self,item):
print("============item clicked=========",item)
def switch_sig(self,sigitem):
print(sigitem)
print("=========self.merge_cols========",self.merge_cols)
w = self.select_sig.itemWidget(sigitem)
label = w.findChild(QLabel,"signame")
signame = label.text()
if signame in self.merge_cols:
signame = signame + '_merge'
chk = w.findChild(QCheckBox,"state")
dest_idx = 0
if chk.isChecked():
for idx,graph in enumerate(self.graph_list):
if graph.name == signame:
self.graph_selection_changed(graph,None,None)
break
def select_sig_item(self,signame):
item_widgt = QWidget()
root = QHBoxLayout()
chk = QCheckBox()
chk.setChecked(True)
chk.setObjectName("state")
name_label = QLabel(signame)
name_label.setObjectName("signame")
#name_label.setFixedSize(40, 25)
value_label = QLabel("=")
value_label.setObjectName(signame+ "_value")
root.addWidget(chk,0,Qt.AlignLeft)
root.addWidget(name_label,1,Qt.AlignLeft)
root.addWidget(value_label,0,Qt.AlignRight)
item_widgt.setLayout(root)
chk.stateChanged.connect(partial(self.select_sig.select_state_changed,signame,chk))
return item_widgt
def push_to_select(self,item):
print(item)
text = item.text()
#self.select_sig.addItem(text)
#idx = self.siglist.indexFromItem(item).row()
#self.siglist.insertItem(idx,text)
item_widgt = self.select_sig_item(text)
new_item = QListWidgetItem()
new_item.setSizeHint(QSize(100, 30))
self.select_sig.addItem(new_item) #插入本listwidget
self.select_sig.setItemWidget(new_item,item_widgt)
def select_state(self,signame,checked):
#if checked:
# self.draw_sig.append(signame)
#else:
# self.draw_sig.remove(signame)
self.redraw(signame,checked)
def search_sig(self,ctext):
res = []
self.search_result.clear()
self.leftarea.setCurrentIndex(1)
for item in self.all_cols:
if ctext.lower() in item.lower():
res.append(item)
if res:
self.search_result.addItems(res)
def nativeEvent(self, eventType, msg):
message = MSG.from_address(msg.__int__())
if message.message == 0x0003: # 窗口移动
pass
return False, 0
def _zero_layer(self):
self.menu = self.menuBar()
self.file_menu = self.menu.addMenu("文件")
self.file_menu.addAction("打开文件")
self.file_menu.addAction("打开文件夹")
self.file_menu.addAction("打开配置")
self.file_menu.addAction("保存")
self.file_menu.triggered[QAction].connect(self.processtrigger)
#h0_wlayout.addWidget(self.menu)
self.analysis_menu = self.menu.addMenu("分析")
self.analysis_menu.addAction(QAction(QIcon(":/icon/耐久每日分析.ico"),"耐久每日分析",self))
self.analysis_menu.addAction(QAction(QIcon(":/icon/耐久极化分析.ico"),"耐久极化分析",self))
self.analysis_menu.addAction(QAction(QIcon(":/icon/分析.ico"),"单个极化分析",self))
self.analysis_menu.addAction(QAction(QIcon(":/icon/耐久Bleeddown分析.ico"),"耐久Bleeddown分析",self))
self.analysis_menu.triggered[QAction].connect(self.analysis_trigger)
self.analysis_menu = self.menu.addMenu("数据处理")
self.analysis_menu.addAction(QAction(QIcon(":/icon/格式转换.ico"),"格式转换",self))
#self.analysis_menu.addAction(QAction(QIcon(":/耐久极化分析.ico"),"合并拆分",self))
self.analysis_menu.triggered[QAction].connect(self.data_process)
def data_process(self):
self.fc_dlg = FormatConversionDialog()
def processtrigger(self,q):
if q.text() == "保存":
filepath, type = QFileDialog.getSaveFileName(self, '文件保存', '/', 'json(*.json)')
self.conf_data['file_list'] = self.f_list
self.conf_data['select_sig'] = self.draw_sig
self.conf_data['merge_cols'] = self.merge_cols
self.conf_data['x_col'] = self.x_col
self.conf_data['line_style'] = self.line_style
open(filepath,'w').write(json.dumps(self.conf_data))
elif q.text() == '打开配置':
filename=QFileDialog.getOpenFileNames(self,'选择文件',os.getcwd(), "All Files(*);;eg Files(*.xlsx *.csv *.MDF)")
json_list = filename[0]
if json_list:
try:
self.conf_f = json_list[0]
self.conf_content = json.loads(open(self.conf_f,'r').read())
print(self.conf_content)
self.f_list = self.conf_content["file_list"]
self.load_data()
except Exception as e:
show_message(self,"err","文件读取失败" + str(e))
elif q.text() == "打开文件":
filename = QFileDialog.getOpenFileNames(self,'选择文件',os.getcwd(), "All Files(*);;eg Files(*.xlsx *.csv *.MDF)")
self.f_list = filename[0]
self.load_data()
print(self.f_list)
elif q.text() == "打开文件夹":
self.data_dir=QFileDialog.getExistingDirectory(None,"选取文件夹","C:/")
self.get_file_list()
self.load_data()
print(self.f_list)
print("menu")
def add_conf_sig(self):
print("addconfsig",self.draw_sig)
for sig in self.draw_sig:
new_item = self.select_sig.select_sig_item(sig)
item = QListWidgetItem()
item.setSizeHint(QSize(130, 33))
self.select_sig.addItem(item) #插入本listwidget
self.select_sig.setItemWidget(item,new_item)
print("==========add sig=========",item)
def load_data(self):
'''self.loading_gif = QMovie('loading.gif')
self.label.setMovie(self.loading_gif)
self.loading_gif.start()'''
if hasattr(self, 'f_list') and self.f_list:
file_str = ",".join(self.f_list)
self.dlg = QProgressDialog()
self.dlg.setWindowIcon(QIcon(":/icon/加载中.ico"))
self.dlg.setRange(0,100)
self.dlg.setAutoClose(True)
self.dlg.setWindowTitle("提示")
self.dlg.setWindowModality(Qt.WindowModal)
self.dlg.setLabelText('加载数据中')
self.dlg.setCancelButtonText('取消')
self.dlg.show()
self.load_data_thread = LoadDataTheard(self.f_list)
self.load_data_thread.res.connect(self.recieve_data)
self.load_data_thread.progress.connect(self.update_progress)
self.load_data_thread.start()
#self.load_data()
def clear_plt_sig(self):
self.line_plot.clearPlottables()
for i in range(self.line_plot.graphCount()):
self.line_plot.removeGraph(i)
self.line_plot.plotLayout().clear()
self.line_plot.removeItem(self.tracer)
self.line_plot.removeItem(self.vline)
self.line_plot.replot()
if hasattr(self, 'select_sig'):
self.select_sig.clear()
if hasattr(self, 'qcp_rect'):
self.qcp_rect = None
self.draw_sig = []
self.plt_color_list = []
self.ax_list = []
#self.merge_cols = []
self.plt_gph_map = {}
self.graph_list = []
def clear_plt(self):
self.line_plot.clearPlottables()
for i in range(self.line_plot.graphCount()):
self.line_plot.removeGraph(i)
if hasattr(self, 'qcp_rect'):
self.qcp_rect = None
self.line_plot.plotLayout().clear()
self.line_plot.removeItem(self.tracer)
self.line_plot.removeItem(self.vline)
#self.line_plot.removeItem(self.vline)
self.line_plot.replot()
self.plt_color_list = []
self.ax_list = []
#self.merge_cols = []
self.graph_list = []
self.plt_gph_map = {}
def recieve_data(self,data):
self.clear_plt_sig()
#self.plt_init()
self.qcp_rect_init()
self.cursor_init()
self.tracer_init()
self.line_plot.replot()
#self.line_plot.plotLayout().clear()
self.total_data = data
self.date_str = extract_date(self.f_list[0])
self.all_cols = self.total_data.columns.tolist()
self.siglist.addItems(self.all_cols)
if 'Time' in self.total_data:
self.time_index = self.total_data['Time']
if 'sPDU_StkOut_iSTK_A' in self.total_data:
self.ydata[0] = self.total_data['sPDU_StkOut_iSTK_A']
else:
show_message(self,"err","sPDU_StkOut_iSTK_A信号未找到")
if hasattr(self, "conf_f") and self.conf_f:
print("==========self.conf_f=======")
self.draw_sig = self.conf_content["select_sig"]
self.merge_cols = self.conf_content["merge_cols"]
self.x_col = self.conf_content['x_col']
self.line_style = self.conf_content.get('line_style','line')
self.add_conf_sig()
self.redraw_plt()
self.merge_yaxis()
self.conf_f = ""
def update_progress(self,prog):
print("progress" + str(prog))
self.dlg.setValue(prog)
def get_file_list(self):
self.f_list = get_flist(self.data_dir)
def analysis_trigger(self,q):
if q.text() == "耐久每日分析":
print("耐久每日分析")
if hasattr(self,'total_data'):
self.ad = DailyAnalysisDialog(self.total_data)
else:
self.ad = DailyAnalysisDialog([])
elif q.text() == '耐久极化分析':
self.durable = DurableAnalysisDialog([])
print("耐久极化分析")
elif q.text() == '单个极化分析':
self.durable = PolarAnalysisDialog()
print("单个极化分析")
elif q.text() == '耐久极化分析':
self.bleed_down = BleedDownAnalysisDialog([])
print("耐久极化分析")
def redraw(self,signame,chk):
for idx,graph in enumerate(self.graph_list):
if graph.name == signame:
print("========name==========",signame,chk)
if chk:
self.graph_list[idx].setVisible(True)
selected_items = self.select_sig.selectedItems()
for item in selected_items:
w = self.select_sig.itemWidget(item)
label = w.findChild(QLabel,"signame")
if label.text() == signame:
self.graph_selection_changed(graph,None,None)
else:
self.graph_list[idx].setVisible(False)
yaxis = self.plt_gph_map.get(graph)
yaxis.setVisible(False)
self.line_plot.replot()
def draw_chart_mul2(self,items):
print("=============draw_chart_mul2===========",items)
self.draw_sig_temp = []
if hasattr(self, "total_data"):
if self.x_col == 'index':
self.zdata = self.total_data.copy()
for item in items:
w = self.select_sig.itemWidget(item)
check_box = w.findChild(QCheckBox,"state")
if check_box and check_box.isChecked():
label = w.findChild(QLabel,"signame")
text = label.text()
self.draw_sig_temp.append(text)
if "" in self.draw_sig:
self.draw_sig.remove("")
self.select_sig_before = len(self.graph_list)+1 - len(self.draw_sig_temp)
self.select_sig_total = len(self.graph_list)+1
for index in range(self.select_sig_before,self.select_sig_total):
#self.vb_ax_init(index)
#print(index)
col = self.draw_sig_temp[index-self.select_sig_before]
self.draw_sig.append(col)
color = self.color_map.get(col,get_color())
self.vb_ax_init(index,self.x_col,self.zdata[col],color,col)
def graphic_widget_init(self):
#pg.setConfigOption("background", "black")
#plt = pg.PlotWidget()
#win对象一定要保留,不保留plt对象没了容器,后面就没法添加子控件了
#self.win = pg.GraphicsLayoutWidget(show=True)
self.win = pg.GraphicsLayout()
#self.win.setContentsMargins(0, 0, 0, 0)
self.win.setSpacing(0)
self.win.setMinimumWidth(0)
#self.win.resize(913,466)
def set_background(self):
plot_gradient = QLinearGradient()
plot_gradient.setStart(0, 0);
plot_gradient.setFinalStop(0, 350);
plot_gradient.setColorAt(0, QColor(0, 0, 0));
plot_gradient.setColorAt(1, QColor(0, 0, 0));
self.line_plot.setBackground(plot_gradient)
def set_axis_color(self,axis,color):
axis.setLabelColor(QColor(color));
axis.setTickLabelColor(QColor(color));
axis.setBasePen(QPen(QColor(color),1,Qt.PenStyle.SolidLine));
axis.setTickPen(QPen(QColor(color)));
axis.setSubTickPen(QPen(QColor(color)))
def plt_init(self):
self.line_plot.plotLayout().clear()
self.line_plot.plottableClick.connect(self.graph_selection_changed)
self.line_plot.setInteraction(QCP.iRangeDrag)
self.line_plot.setInteraction(QCP.iRangeZoom)
self.line_plot.mouseMove.connect(self.mouse_move)
self.line_plot.mousePress.connect(self.mouse_pressed)
#self.line_plot.mousePress.connect(self.mouse_ispressed)
self.line_plot.mouseRelease.connect(self.mouse_release)
self.set_background()
self.qcp_rect_init()
self.cursor_init()
self.tracer_init()
self.line_plot.replot()
def qcp_rect_init(self):
self.qcp_rect = QCPAxisRect(self.line_plot,True)
self.line_plot.plotLayout().addElement(0,0,self.qcp_rect)
self.x_axis = self.qcp_rect.axis(QCPAxis.atBottom)
self.set_axis_color(self.line_plot.xAxis,"#ffffff")
self.set_axis_color(self.line_plot.yAxis,"#ffffff")
self.line_plot.xAxis.grid().setPen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
self.line_plot.xAxis.grid().setSubGridVisible(True)
self.line_plot.xAxis.grid().setLayer("grid")
self.line_plot.xAxis.grid().setSubGridPen(QPen(QColor("#003000"),1,Qt.PenStyle.DashLine))
self.line_plot.xAxis.setTickLength(0,6)
self.line_plot.xAxis.setSubTickLength(0,3)
self.line_plot.xAxis.grid().setZeroLinePen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
self.line_plot.yAxis.grid().setPen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
self.line_plot.yAxis.grid().setSubGridVisible(True)
self.line_plot.yAxis.grid().setSubGridPen(QPen(QColor("#003000"),1,Qt.PenStyle.DashLine))
self.line_plot.yAxis.grid().setZeroLinePen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
self.line_plot.yAxis.grid().setLayer("grid")
self.line_plot.yAxis.setTickLength(0,6)
self.line_plot.yAxis.setSubTickLength(0,3)
self.line_plot.replot()
def cursor_init(self):
self.vline = QCPItemStraightLine(self.line_plot)
self.vline.setLayer("overlay")
linesPen = QPen(QColor("#00FFFF"),1,Qt.PenStyle.SolidLine)
lineSelectedPen = QPen(QColor("#ffFFFF"),1,Qt.PenStyle.SolidLine)
self.vline.setPen(linesPen)
self.vline.setSelectedPen(lineSelectedPen)
self.vline.setClipToAxisRect(True)
self.vline.point1.setTypeX(QCPItemPosition.ptPlotCoords)
self.vline.point1.setTypeY(QCPItemPosition.ptPlotCoords)
self.vline.point2.setTypeX(QCPItemPosition.ptPlotCoords)
self.vline.point2.setTypeY(QCPItemPosition.ptPlotCoords)
self.vline.setVisible(False)
self.vline.setSelectable(True)
self.vline.selectionChanged.connect(self.line_selection_changed)
def tracer_init(self):
self.tracer = QCPItemTracer(self.line_plot)
self.tracer.setPen(QPen(QColor("#ffffff"),1,Qt.PenStyle.DashLine))
self.tracer.setStyle(QCPItemTracer.TracerStyle.tsCrosshair)
def line1_selection_changed(self,selected):
print("=======selected=====",selected)
if not selected:
self.line_plot.setInteraction(QCP.iRangeDrag,True)
def line_selection_changed(self,selected):
print(selected)
if not selected:
self.line_plot.setInteraction(QCP.iRangeDrag,True)
def mouse_move(self,event):
if self.line_plot.xAxis is not None:
#下面的代码很关键
self.x = self.line_plot.xAxis.pixelToCoord(event.pos().x())
if self.mouse_ispressed and (self.vline.selected() or (self.vline1 and self.vline1.selected())):
#print(x)
self.tracer.setGraph(self.graph) #设置游标吸附于指定曲线
self.tracer.setGraphKey(self.x); #将游标横坐标(key)设置成刚获得的横坐标数据x
self.tracer.setInterpolating(True); #游标的纵坐标可以通过曲线数据线性插值自动获得
self.tracer.updatePosition(); #使得刚设置游标的横纵坐标位置生效
if self.vline.selected():
self.x1 = self.x
self.vline.point1.setCoords(self.x, 100)
self.vline.point2.setCoords(self.x, 0)
elif self.vline1.selected():
self.x2 = self.x
self.vline1.point1.setCoords(self.x, 100)
self.vline1.point2.setCoords(self.x, 0)
self.vline_moved(self.vline)
self.line_plot.replot()
def mouse_pressed(self,event):
self.mouse_ispressed = True
x = self.line_plot.xAxis.pixelToCoord(event.pos().x())
dis = self.vline.selectTest(event.pos(),True)
if hasattr(self,"vline1") and self.vline1:
dis1 = self.vline1.selectTest(event.pos(),True)
if dis1 < 5:
self.vline1.setSelected(True)
print("===========dis1==========",dis1)
self.line_plot.setInteraction(QCP.iRangeDrag,False)
self.tracer.setVisible(True)
print(event)
if dis < 5:
self.vline.setSelected(True)
print(dis)
#self.line_plot.setCurrentLayer("overlay")
self.line_plot.setInteraction(QCP.iRangeDrag,False)
self.tracer.setVisible(True)
if not self.vline.visible():
self.vline.setVisible(True)
self.vline.point1.setCoords(x, 100)
self.vline.point2.setCoords(x, 100 - 100.0)
self.x1 = x
self.line_plot.replot()
def mouse_release(self,event):
print("release")
self.tracer.setVisible(False)
self.mouse_ispressed = False
self.vline.setSelected(False)
if hasattr(self,"vline1") and self.vline1:
self.vline1.setSelected(False)
self.line_plot.setInteraction(QCP.iRangeDrag,True)
self.line_plot.replot()
def vline_moved(self,vline):
#print(vline.value())
print()
if self.x_col == 'index':
v = int(self.x)
else:
v = round(self.x,2)
if self.multi_flag:
#print(self.multi_flag)
try:
self.x1_value = (self.zdata[self.x_col] - self.x1).abs().idxmin()
self.x2_value = (self.zdata[self.x_col] - self.x2).abs().idxmin()
for i in range(self.select_sig.count()):
item = self.select_sig.item(i)
w = self.select_sig.itemWidget(item)
label = w.findChild(QLabel,"signame")
signame = label.text()
value_label = w.findChild(QLabel,"value")
if self.x1_value < self.zdata.shape[0]:
value_label.setText("= %.2f" % (self.zdata[signame][self.x2_value] - self.zdata[signame][self.x1_value]))
self.time_label.setText("= %.21s" % (self.zdata['Time'][self.x2_value] - self.zdata['Time'][self.x1_value]))
except:
if vline is self.vline:
self.x1_value = self.x1
else:
self.x2_value = self.x2
else:
self.x1_value = (self.zdata[self.x_col] - self.x1).abs().idxmin()
for i in range(self.select_sig.count()):
item = self.select_sig.item(i)
w = self.select_sig.itemWidget(item)
label = w.findChild(QLabel,"signame")
signame = label.text()
value_label = w.findChild(QLabel,"value")
if self.x1_value < self.zdata.shape[0]:
if isinstance(self.zdata[signame][self.x1_value],float):
value_label.setText("= %.2f" % self.zdata[signame][self.x1_value])
else:
value_label.setText("= %s" % self.zdata[signame][self.x1_value])
self.time_label.setText("time = %.21s" % self.zdata['Time'][self.x1_value])
def state_changed(self,aa):
print("state changed",aa)
def reset_plt(self):
'''绘图重置,主要是重置x轴坐标为index'''
self.clear_plt()
self.qcp_rect_init()
self.cursor_init()
self.tracer_init()
self.line_plot.replot()
self.draw_sig_temp = []
if hasattr(self, "total_data"):
self.zdata = self.total_data.copy()
if "" in self.draw_sig:
self.draw_sig.remove("")
#for col in self.draw_sig:
# self.zdata[col] = self.total_data[col]
self.select_sig_before = self.select_sig.count() - len(self.draw_sig)
self.select_sig_total = self.select_sig.count()
for index,col in enumerate(self.draw_sig):
#self.vb_ax_init(index)
print(index)
color = self.color_map.get(col,get_color())
self.vb_ax_init(index,'index',self.zdata[col],color,col)
for i in range(self.select_sig.count()):
item = self.select_sig.item(i)
w = self.select_sig.itemWidget(item)
check_box = w.findChild(QCheckBox,"state")
chk = check_box.isChecked()
label = w.findChild(QLabel,"signame")
signame = label.text()
self.redraw(signame,chk)
def redraw_plt(self):
print("=======x_col========",self.x_col)
self.clear_plt()
self.qcp_rect_init()
self.cursor_init()
self.tracer_init()
self.line_plot.replot()
self.draw_sig_temp = []
if hasattr(self, "total_data"):
self.zdata = self.total_data.sort_values(by=self.x_col)
#self.zdata = self.zdata.reset_index()
for i in range(self.select_sig.count()):
item = self.select_sig.item(i)
w = self.select_sig.itemWidget(item)
check_box = w.findChild(QCheckBox,"state")
if check_box and check_box.isChecked():
label = w.findChild(QLabel,"signame")
text = label.text()
self.draw_sig_temp.append(text)
if "" in self.draw_sig:
self.draw_sig.remove("")
#for col in self.draw_sig:
# self.zdata[col] = self.total_data[col]
self.select_sig_before = self.select_sig.count() - len(self.draw_sig_temp)
self.select_sig_total = self.select_sig.count()
for index,col in enumerate(self.draw_sig):
#self.vb_ax_init(index)
print(index)
color = self.color_map.get(col,get_color())
self.vb_ax_init(index,self.x_col,self.zdata[col],color,col)
def my_list_widget_context(self, point):
item = self.siglist.itemAt(point)
if item:
self.x_col = item.text()
popMenu = QMenu()
popMenu.addAction(QAction(u'设为x轴', self,triggered=self.redraw_plt))
popMenu.exec_(QCursor.pos())
print(self.x_col)
def my_search_list_widget_context(self, point):
item = self.search_result.itemAt(point)
if item:
self.x_col = item.text()
popMenu = QMenu()
popMenu.addAction(QAction(u'设为x轴', self,triggered=self.redraw_plt))
popMenu.exec_(QCursor.pos())
print(self.x_col)
def select_sig_context(self, point):
print("select_sig_context")
selected_items = self.select_sig.selectedItems()
item = self.select_sig.itemAt(point)
popMenu = QMenu()
if len(selected_items) > 1:
popMenu.addAction(QAction(u'合并y轴', self,triggered=self.merge_yaxis))
elif item:
w = self.select_sig.itemWidget(item)
label = w.findChild(QLabel,"signame")
self.x_col = label.text()
print("==========item========",item)
print("==========item========",self.x_col)
popMenu.addAction(QAction(u'设为x轴', self,triggered=self.redraw_plt))
popMenu.exec_(QCursor.pos())
def merge_yaxis(self):
print("merge_yaxis")
#self.merge_cols = []
#如果self.merge_cols有值,应该时从conf中读取的
if self.merge_cols:
print(self.merge_cols)
self.hide_merge_cols()
self.create_merge_plt()
else:
merge_items = self.select_sig.selectedItems()
for item in merge_items:
w = self.select_sig.itemWidget(item)
label = w.findChild(QLabel,"signame")
col = label.text()
self.merge_cols.append(col)
self.hide_merge_cols()
self.create_merge_plt()
print(self.merge_cols)
def hide_merge_cols(self):
if self.merge_cols:
for graph in self.graph_list:
if graph.name in self.merge_cols:
graph.setVisible(False)
def create_merge_plt(self):
label_name = ",".join(self.merge_cols)
idx = len(self.ax_list)
#self.ax = pg.AxisItem('left',pen=(150,150,150),name='merge',textPen=(150,150,150))
self.ax = self.qcp_rect.addAxis(QCPAxis.atLeft)
self.ax.setLayer("axes")
self.ax.setLabel(label_name)
self.ax.setTickLength(0,6)
self.ax.setSubTickLength(0,3)
print(dir(QCPLineEnding))
self.ax.setUpperEnding(QCPLineEnding(QCPLineEnding.esNone))
self.ax.setLowerEnding(QCPLineEnding(QCPLineEnding.esNone))
self.ax.grid().setVisible(True)
self.ax.grid().setLayer("grid")
self.ax.grid().setSubGridVisible(True)
self.ax.grid().setSubGridPen(QPen(QColor("#003000"),1,Qt.PenStyle.DashLine))
self.ax.grid().setZeroLinePen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
color = "#ffffff"
self.set_axis_color(self.ax,color)
print(self.ax)
#self.graph_selection_changed(self.graph,None,None)
for col in self.merge_cols:
color = self.color_map.get(col,get_color())
xdata = self.total_data[self.x_col]
ydata = self.total_data[col]
self.graph = self.line_plot.addGraph(self.x_axis,self.ax)
self.graph.setAntialiased(False)
self.graph.name = col+ "_merge"
self.graph.setPen(QPen(QColor(color)))
if self.line_style == 'line':
self.graph.setPen(QPen(QColor(color)))
if self.line_style == 'scatter':
self.graph.setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssCircle,2))
if self.line_style == 'ls':
self.graph.setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssCircle,2))
self.graph.setData(xdata,ydata)
#self.tracer.setGraph(self.graph)
#self.graph.valueAxis().setRange(ydata.min() - ydata.max() *0.05, ydata.max() + ydata.min() * 0.05)
self.graph.rescaleAxes(True)
self.plt_color_list.append(color)
self.graph_list.append(self.graph)
self.x_axis.setLabel(self.x_col)
self.plt_gph_map[self.graph] = self.ax
self.graph_list.append(self.graph)
self.graph_selection_changed(self.graph,None,None)
self.plt_color_list.append(color)
self.ax_list.append(self.ax)
self.line_plot.replot()
def set_line_style(self,line_type):
if line_type == 'line':
for i in range(len(self.graph_list)):
self.graph_list[i].setLineStyle(QCPGraph.lsLine)
self.graph_list[i].setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssNone,3))
elif line_type == 'scatter':
for i in range(len(self.graph_list)):
self.graph_list[i].setLineStyle(QCPGraph.lsNone)
self.graph_list[i].setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssDisc,3))
else:
for i in range(len(self.graph_list)):
self.graph_list[i].setLineStyle(QCPGraph.lsLine)
self.graph_list[i].setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssDisc,3))
self.line_plot.replot()
def vb_ax_init(self,idx,xdata_name,ydata,color,name):
if xdata_name == 'index':
xdata = self.zdata.index
else:
xdata = self.zdata[xdata_name]
print("=====================idx========================",idx)
if xdata_name == 'abstimestamps':
self.x_axis.format = 'datetime'
dateTimeTicker = QCPAxisTickerDateTime()
dateTimeTicker.setDateTimeFormat("yyyy-MM-dd hh:mm:ss")
self.x_axis.setTicker(dateTimeTicker)
else:
self.x_axis.format = "number"
for i,ax in enumerate(self.ax_list):
self.ax_list[i].setVisible(False)
if idx == 0:
self.ax = self.qcp_rect.axis(QCPAxis.atLeft,0)
else:
self.ax = self.qcp_rect.addAxis(QCPAxis.atLeft)
self.ax.setLayer("axes")
self.ax.setTickLength(0,6)
self.ax.setSubTickLength(0,3)
self.ax.setLabel(name)
self.ax.setUpperEnding(QCPLineEnding(QCPLineEnding.esNone))
self.ax.setLowerEnding(QCPLineEnding(QCPLineEnding.esNone))
self.ax.grid().setVisible(True)
self.ax.grid().setLayer("grid")
self.ax.grid().setSubGridVisible(True)
self.ax.grid().setPen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
self.ax.grid().setSubGridPen(QPen(QColor("#003000"),1,Qt.PenStyle.DashLine))
self.ax.grid().setZeroLinePen(QPen(QColor("#008000"),1,Qt.PenStyle.DashLine))
self.set_axis_color(self.ax,color)
self.graph = self.line_plot.addGraph(self.x_axis,self.ax)
self.graph.setAntialiased(False)
self.graph.name = name
self.graph.setPen(QPen(QColor(color)))
if self.line_style == 'line':
self.graph.setLineStyle(QCPGraph.lsLine)
self.graph.setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssNone,3))
if self.line_style == 'scatter':
self.graph.setLineStyle(QCPGraph.lsNone)
self.graph.setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssDisc,3))
if self.line_style == 'ls':
self.graph.setLineStyle(QCPGraph.lsLine)
self.graph.setScatterStyle(QCPScatterStyle(QCPScatterStyle.ssDisc,3))
self.graph.setData(xdata,ydata)
#self.tracer.setGraph(self.graph)
self.graph.valueAxis().setRange(ydata.min() - ydata.max() *0.05, ydata.max() + ydata.min() * 0.05)
self.graph.keyAxis().setRange(xdata.min(), xdata.max())
self.graph.rescaleAxes(True)
self.graph.rescaleKeyAxis(True)
self.plt_color_list.append(color)
self.graph_list.append(self.graph)
self.ax_list.append(self.ax)
self.x_axis.setLabel(xdata_name)
self.plt_gph_map[self.graph] = self.ax
self.graph_selection_changed(self.graph,None,None)
self.line_plot.replot()
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
if __name__ == '__main__':
multiprocessing.freeze_support()
#cgitb.enable(format="text")
app = QApplication(sys.argv)
#apply_stylesheet(app, theme='light_blue.xml')
#qssfile = "./style/qss/flatgray.css"
#qssstyle = read_qss(qssfile)
#app.setStyleSheet(qssstyle)
splash = QSplashScreen()
#初始图片
splash.setPixmap(QPixmap('数据分析.png')) # 设置背景图片
#初始文本
splash.showMessage("加载... 0%", QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom, QtCore.Qt.black)
# 设置字体
splash.setFont(QFont('微软雅黑', 10))
# 显示启动界面
splash.show()
app.processEvents() # 处理主进程事件
#主窗口
#window.load_data(splash) # 加载数据
win = MainWindow(sys.argv)
splash.finish(win)
splash.deleteLater()
sys.exit(app.exec_())