分析工具QCustomPlot2版

        这周主要实现了绘图控件从pyqtgraph到QCustomPlot2的迁移,总体感觉,首先这个绘图控件据说出自大神之手,质量自然没得说,在cpp的qt生态特别流行,因为网上我只搜到一篇python的,其它都是cpp版本的代码,虽然python里用的人很少,但是不能掩盖大神的光辉,这周做迁移的过程,虽然有些磕磕绊绊,但是最终还是顺利把之前在pyqtgraph上实现的功能全部在plot2上实现了,不得不说,用这个控件实现,同样的功能,实现代码不但减少了,而且问题很少,控件本身基本没有发现bug,不像pyqtgraph,有明显的bug(当然也可能是我菜),同时,在pyqtgraph上出现的性能问题在这个控件也没有了,pyqtgraph绘制散点图时,数据过多时就会很卡,而折线图就很丝滑,不知道什么问题,(#而在QCustomPlot2上画散点图和折线图基本没有性能上的差别),这块纠正一下,这个控件散点图在数据量大的时候也有问题,特别是在tracer移动时表现特别明显,这块应该和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_())

猜你喜欢

转载自blog.csdn.net/zy1620454507/article/details/127864912