|
@@ -0,0 +1,389 @@
|
|
|
|
+#include "chart_file.h"
|
|
|
|
+#include "ui_chart_file.h"
|
|
|
|
+
|
|
|
|
+#include <QDebug>
|
|
|
|
+#include <QMessageBox>
|
|
|
|
+#include <QFile>
|
|
|
|
+
|
|
|
|
+chart_file::chart_file(QWidget *parent) :
|
|
|
|
+ QWidget(parent),
|
|
|
|
+ ui(new Ui::chart_file),
|
|
|
|
+ chart(new QChart),
|
|
|
|
+ timer(new QTimer),
|
|
|
|
+ count(0)
|
|
|
|
+{
|
|
|
|
+ ui->setupUi(this);
|
|
|
|
+ QStandardItemModel* model = treeModel->tree_set();
|
|
|
|
+ ui->tree_set->setModel(model);
|
|
|
|
+ ui->tree_set->expandAll();
|
|
|
|
+ // 将 QTreeView 的 clicked 信号连接到 handleTreeItemClicked 槽函数
|
|
|
|
+ connect(ui->tree_set, &QTreeView::clicked, this, &chart_file::handleTreeItemClicked);
|
|
|
|
+ // 初始化变量
|
|
|
|
+ time=nullptr;
|
|
|
|
+ point1=nullptr;
|
|
|
|
+ point2=nullptr;
|
|
|
|
+
|
|
|
|
+ // 设置点的数量
|
|
|
|
+ pointsSize=200;
|
|
|
|
+
|
|
|
|
+ // 初始化字体颜色
|
|
|
|
+ initFontColor();
|
|
|
|
+
|
|
|
|
+ // 初始化读取数据
|
|
|
|
+ initReadData();
|
|
|
|
+
|
|
|
|
+ // 设置定时器间隔为100毫秒
|
|
|
|
+ timer->setInterval(100);
|
|
|
|
+
|
|
|
|
+ // 启动定时器
|
|
|
|
+ timer->start();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+chart_file::~chart_file()
|
|
|
|
+{
|
|
|
|
+ // 释放UI对象和动态分配的内存
|
|
|
|
+ delete ui;
|
|
|
|
+
|
|
|
|
+ // 释放动态分配的数组内存
|
|
|
|
+ delete [] time;
|
|
|
|
+ delete [] point1;
|
|
|
|
+ delete [] point2;
|
|
|
|
+
|
|
|
|
+ // 释放二维数组tempDis的内存
|
|
|
|
+ for (int i=0;i<pointsNum;i++) {
|
|
|
|
+ delete [] tempDis[i];
|
|
|
|
+ }
|
|
|
|
+ delete [] tempDis;
|
|
|
|
+}
|
|
|
|
+void chart_file::setTreeModel(tree_model_set* model)
|
|
|
|
+{
|
|
|
|
+ treeModel = model; // 设置 tree_model_set 实例
|
|
|
|
+}
|
|
|
|
+void chart_file::handleTreeItemClicked(const QModelIndex &index) {
|
|
|
|
+ // 转发信号
|
|
|
|
+ emit treeItemClicked(index);
|
|
|
|
+}
|
|
|
|
+// 鼠标滚轮事件处理函数
|
|
|
|
+void chart_file::wheelEvent(QWheelEvent *event)
|
|
|
|
+{
|
|
|
|
+ if (event->angleDelta().y() > 0) {
|
|
|
|
+ chart->zoom(1.1);
|
|
|
|
+ } else {
|
|
|
|
+ chart->zoom(10/1.1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ QWidget::wheelEvent(event);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void chart_file::initUI()
|
|
|
|
+{
|
|
|
|
+ initChart();
|
|
|
|
+}
|
|
|
|
+// 初始化图表
|
|
|
|
+void chart_file::initChart()
|
|
|
|
+{
|
|
|
|
+ //chart->createDefaultAxes();
|
|
|
|
+
|
|
|
|
+ /**修改**/
|
|
|
|
+ axisX=new QValueAxis();
|
|
|
|
+ axisX->setTitleFont(QFont("Microsoft YaHei", 10, QFont::Normal, true));
|
|
|
|
+ axisX->setTitleText("Time(s)");
|
|
|
|
+ axisX->setGridLineVisible(true);
|
|
|
|
+ chart->addAxis(axisX,Qt::AlignBottom);
|
|
|
|
+
|
|
|
|
+ axisY=new QValueAxis();
|
|
|
|
+ axisY->setTitleFont(QFont("Microsoft YaHei", 10, QFont::Normal, true));
|
|
|
|
+ axisY->setTitleText("值");
|
|
|
|
+ axisY->setGridLineVisible(true);
|
|
|
|
+ chart->addAxis(axisY,Qt::AlignLeft);
|
|
|
|
+ for (int i=0;i<pointsNum;i++) {
|
|
|
|
+ series[i]->attachAxis(axisX);
|
|
|
|
+ series[i]->attachAxis(axisY);
|
|
|
|
+ }
|
|
|
|
+ /**修改**/
|
|
|
|
+ chart->legend()->hide();
|
|
|
|
+ chartView = new QChartView(chart);
|
|
|
|
+ chartView->setRenderHint(QPainter::Antialiasing);//抗锯齿渲染
|
|
|
|
+ ui->mainvertical->addWidget(chartView);
|
|
|
|
+}
|
|
|
|
+// 初始化信号槽连接
|
|
|
|
+// 初始化槽函数,连接信号和槽
|
|
|
|
+void chart_file::initSlot()
|
|
|
|
+{
|
|
|
|
+ connect(timer, SIGNAL(timeout()), this, SLOT(timerSlot()));
|
|
|
|
+ connect(ui->allRadioButton,SIGNAL(clicked()),this,SLOT(selectAll()));
|
|
|
|
+ connect(ui->invertRadioButton,SIGNAL(clicked()),this,SLOT(invertSelect()));
|
|
|
|
+
|
|
|
|
+ for (int i=0;i<pointsNum;i++) {
|
|
|
|
+ connect(checkBoxVector.at(i),SIGNAL(toggled(bool)),this,SLOT(checkboxChanged()));
|
|
|
|
+ connect(series[i], SIGNAL(hovered(QPointF, bool)), this, SLOT(tipSlot(QPointF,bool)));
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// 添加图表数据
|
|
|
|
+void chart_file::addChartData(float time, float *pointsDis)
|
|
|
|
+{
|
|
|
|
+ float globalMinX = time;
|
|
|
|
+ float globalMaxX = time;
|
|
|
|
+ float globalMinY = pointsDis[0];
|
|
|
|
+ float globalMaxY = pointsDis[0];
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < pointsNum; i++)
|
|
|
|
+ {
|
|
|
|
+ QVector<QPointF> data = series[i]->pointsVector();
|
|
|
|
+
|
|
|
|
+ data.append(QPointF(time, pointsDis[i]));
|
|
|
|
+
|
|
|
|
+ float minX = data.at(0).x();
|
|
|
|
+ float maxX = data.at(0).x();
|
|
|
|
+ float minY = data.at(0).y();
|
|
|
|
+ float maxY = data.at(0).y();
|
|
|
|
+
|
|
|
|
+ for (int j = 0; j < data.size(); j++) {
|
|
|
|
+ if (minY > data.at(j).y())
|
|
|
|
+ minY = data.at(j).y();
|
|
|
|
+ if (maxY < data.at(j).y())
|
|
|
|
+ maxY = data.at(j).y();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (i == 0)
|
|
|
|
+ {
|
|
|
|
+ for (int j = 0; j < data.size(); j++) {
|
|
|
|
+ if (minX > data.at(j).x())
|
|
|
|
+ minX = data.at(j).x();
|
|
|
|
+ if (maxX < data.at(j).x())
|
|
|
|
+ maxX = data.at(j).x();
|
|
|
|
+ }
|
|
|
|
+ globalMinX = minX;
|
|
|
|
+ globalMaxX = maxX;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ globalMinY = globalMinY < minY ? globalMinY : minY;
|
|
|
|
+ globalMaxY = globalMaxY > maxY ? globalMaxY : maxY;
|
|
|
|
+
|
|
|
|
+ series[i]->replace(data);
|
|
|
|
+
|
|
|
|
+ tempDis[i][0] = pointsDis[i];
|
|
|
|
+ tempDis[i][1] = maxY;
|
|
|
|
+ tempDis[i][2] = minY;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ addTableData(tempDis);
|
|
|
|
+
|
|
|
|
+ axisX->setRange(globalMinX, globalMaxX);
|
|
|
|
+ axisY->setRange(globalMinY - (globalMaxY - globalMinY) * 0.1, globalMaxY + (globalMaxY - globalMinY) * 0.1);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+// 设置点的数量
|
|
|
|
+void chart_file::setPointsNum(int num)
|
|
|
|
+{
|
|
|
|
+ if(num>9)
|
|
|
|
+ {
|
|
|
|
+ QMessageBox::information(this,"Warnning","The number of points exceed 9!");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tempDis=new float*[num];
|
|
|
|
+
|
|
|
|
+ pointsNum=num;
|
|
|
|
+ //model->setRowCount(num);
|
|
|
|
+
|
|
|
|
+ // 该函数用于初始化图表中的数据系列,并为每个数据系列设置颜色和临时数据存储空间
|
|
|
|
+ // 参数:
|
|
|
|
+ // - pointsNum: 数据系列的数量
|
|
|
|
+ // - series: 指向数据系列数组的指针
|
|
|
|
+ // - colorTable: 包含每个数据系列颜色的QList
|
|
|
|
+ // - chart: 指向图表对象的指针
|
|
|
|
+ // - tempDis: 指向临时数据存储数组的指针
|
|
|
|
+ for (int i=0;i<pointsNum;i++) {
|
|
|
|
+ series[i]=new QLineSeries();
|
|
|
|
+ series[i]->setColor(colorTable.at(i));
|
|
|
|
+ chart->addSeries(series[i]);
|
|
|
|
+ tempDis[i]=new float[3];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ initUI();
|
|
|
|
+ initTable(num);
|
|
|
|
+ initSlot();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 添加表格数据
|
|
|
|
+void chart_file::addTableData(float **pointsDis)
|
|
|
|
+{
|
|
|
|
+ for (int i=0;i<pointsNum;i++) {
|
|
|
|
+ for (int j=0;j<3;j++) {
|
|
|
|
+ model->setItem(i, j+1, new QStandardItem(QString::number(pointsDis[i][j])));
|
|
|
|
+ model->item(i,j+1)->setForeground(QBrush(colorTable.at(i)));
|
|
|
|
+ model->item(i, j+1)->setTextAlignment(Qt::AlignCenter);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 初始化表格
|
|
|
|
+void chart_file::initTable(int pointsNumber)
|
|
|
|
+{
|
|
|
|
+ ui->allRadioButton->setChecked(true);
|
|
|
|
+
|
|
|
|
+ model = new QStandardItemModel();
|
|
|
|
+ model->setColumnCount(4);
|
|
|
|
+ model->setHorizontalHeaderItem(0, new QStandardItem(QObject::tr("曲线编号")));
|
|
|
|
+ model->setHorizontalHeaderItem(1, new QStandardItem(QObject::tr("Displacements(mm)")));
|
|
|
|
+ model->setHorizontalHeaderItem(2, new QStandardItem(QObject::tr("Peak(mm)")));
|
|
|
|
+ model->setHorizontalHeaderItem(3, new QStandardItem(QObject::tr("Valley(mm)")));
|
|
|
|
+
|
|
|
|
+ ui->tableView->setModel(model);
|
|
|
|
+
|
|
|
|
+ ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
|
|
+ ui->tableView->verticalHeader()->hide();
|
|
|
|
+ ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
|
|
|
+ ui->tableView->setColumnWidth(1,100);
|
|
|
|
+
|
|
|
|
+ model->setRowCount(pointsNumber);
|
|
|
|
+
|
|
|
|
+ // 此函数用于在表格视图中创建多个复选框,并将它们添加到模型中
|
|
|
|
+ // 每个复选框的标签为 "Point" 加上序号,并根据颜色数组设置样式
|
|
|
|
+ // 最后,将复选框添加到表格视图中,并设置其初始状态为选中
|
|
|
|
+ QString str="";
|
|
|
|
+ for (int i=0;i<pointsNumber;i++) {
|
|
|
|
+ str="Point";
|
|
|
|
+ str+=QString::number(i+1);
|
|
|
|
+ QCheckBox *box=new QCheckBox(str,ui->tableView);
|
|
|
|
+ box->setStyleSheet(strColor[i]);
|
|
|
|
+
|
|
|
|
+ checkBoxVector.append(box);
|
|
|
|
+
|
|
|
|
+ model->setItem(i, 0, new QStandardItem(""));
|
|
|
|
+ ui->tableView->setIndexWidget(model->index(i,0),checkBoxVector.at(i));
|
|
|
|
+ model->item(i, 0)->setTextAlignment(Qt::AlignCenter);
|
|
|
|
+ checkBoxVector.at(i)->setChecked(true);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 全选所有点
|
|
|
|
+void chart_file::selectAll()
|
|
|
|
+{
|
|
|
|
+ for(int i=0;i<checkBoxVector.size();i++)
|
|
|
|
+ checkBoxVector.at(i)->setChecked(true);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 初始化字体颜色
|
|
|
|
+void chart_file::initFontColor()
|
|
|
|
+{
|
|
|
|
+ colorTable.append(QColor(255,0,0));//red
|
|
|
|
+ colorTable.append(QColor(0,0,255));//blue
|
|
|
|
+ colorTable.append(QColor(0,255,0));//green
|
|
|
|
+ colorTable.append(QColor(139,0,0));//dark red
|
|
|
|
+ colorTable.append(QColor(255,255,0));//yellow
|
|
|
|
+ colorTable.append(QColor(0,0,0));//black
|
|
|
|
+ colorTable.append(QColor(128,42,42));//棕色
|
|
|
|
+ colorTable.append(QColor(160,32,240));//purple
|
|
|
|
+ colorTable.append(QColor(0,255,255));//青色
|
|
|
|
+
|
|
|
|
+ strColor[0]="QCheckBox{color:rgb(255,0,0)}";
|
|
|
|
+ strColor[1]="QCheckBox{color:rgb(0,0,255)}";
|
|
|
|
+ strColor[2]="QCheckBox{color:rgb(0,255,0)}";
|
|
|
|
+ strColor[3]="QCheckBox{color:rgb(139,0,0)}";
|
|
|
|
+ strColor[4]="QCheckBox{color:rgb(255,255,0)}";
|
|
|
|
+ strColor[5]="QCheckBox{color:rgb(128,42,42)}";
|
|
|
|
+ strColor[7]="QCheckBox{color:rgb(160,32,240)}";
|
|
|
|
+ strColor[8]="QCheckBox{color:rgb(0,255,255)}";
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 反选所有点
|
|
|
|
+void chart_file::invertSelect()
|
|
|
|
+{
|
|
|
|
+ for(int i=0;i<checkBoxVector.size();i++){
|
|
|
|
+ if(checkBoxVector.at(i)->checkState())
|
|
|
|
+ checkBoxVector.at(i)->setChecked(false);
|
|
|
|
+ else
|
|
|
|
+ checkBoxVector.at(i)->setChecked(true);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 复选框状态改变处理函数
|
|
|
|
+void chart_file::checkboxChanged()
|
|
|
|
+{
|
|
|
|
+ for (int i=0;i<pointsNum;i++) {
|
|
|
|
+ if(checkBoxVector.at(i)->checkState()){
|
|
|
|
+ series[i]->setVisible(true);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ series[i]->setVisible(false);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 初始化读取数据
|
|
|
|
+void chart_file::initReadData()
|
|
|
|
+{
|
|
|
|
+ QString name = "D:/document/code_all/Qt/QtChartWidget-master/QtChartWidget/data/3.txt";
|
|
|
|
+
|
|
|
|
+ QFile readFile(name);
|
|
|
|
+ int i=0;
|
|
|
|
+
|
|
|
|
+ if(!readFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
|
|
+ {
|
|
|
|
+ QMessageBox::information(nullptr, "Warning", "Fail to read the file");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ QTextStream readStream(&readFile);
|
|
|
|
+ QString line;
|
|
|
|
+
|
|
|
|
+ time=new float[10000];
|
|
|
|
+ point1=new float[10000];
|
|
|
|
+ point2= new float[10000];
|
|
|
|
+ QString str="";
|
|
|
|
+
|
|
|
|
+ while(i<10000)
|
|
|
|
+ {
|
|
|
|
+ line=readStream.readLine();
|
|
|
|
+
|
|
|
|
+ if(!line.isEmpty())
|
|
|
|
+ {
|
|
|
|
+ QStringList list = line.split(QRegularExpression(","), Qt::SkipEmptyParts);
|
|
|
|
+
|
|
|
|
+ time[i]=list.at(0).toFloat();
|
|
|
|
+ point1[i]=list.at(1).toFloat();
|
|
|
|
+ point2[i]=list.at(2).toFloat();
|
|
|
|
+
|
|
|
|
+ if(i<20)
|
|
|
|
+ {
|
|
|
|
+ str+=QString::number(time[i]);
|
|
|
|
+ str+=", ";
|
|
|
|
+ str+=QString::number(point1[i]);
|
|
|
|
+ str+=", ";
|
|
|
|
+ str+=QString::number(point2[i]);
|
|
|
|
+ str+="\n";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ i++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ readFile.close();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 添加数据
|
|
|
|
+void chart_file::addData()
|
|
|
|
+{
|
|
|
|
+ float y[2];
|
|
|
|
+ y[0]=point1[count];
|
|
|
|
+ y[1]=point2[count];
|
|
|
|
+
|
|
|
|
+ addChartData(time[count],y);
|
|
|
|
+
|
|
|
|
+ count++;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 定时器槽函数
|
|
|
|
+void chart_file::timerSlot()
|
|
|
|
+{
|
|
|
|
+ if (QObject::sender() == timer) {
|
|
|
|
+ addData();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|