From fc3853c3caa3b635e0af1563ee12e5bd219b66c9 Mon Sep 17 00:00:00 2001
From: tangchao0503 <735056338@qq.com>
Date: Tue, 16 Jun 2026 15:31:06 +0800
Subject: [PATCH] =?UTF-8?q?add=EF=BC=8C=E8=AE=A1=E5=88=92=E9=87=87?=
=?UTF-8?q?=E9=9B=8613=EF=BC=9A=20=E4=BC=98=E5=8C=96=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
HPPA/HPPA.cpp | 31 +-
HPPA/HPPA.h | 1 -
HPPA/HPPA.vcxproj | 2 +
HPPA/HPPA.vcxproj.filters | 6 +
HPPA/PathLine.cpp | 319 +++++++++++++++++++++
HPPA/PathLine.h | 51 ++++
HPPA/TaskTreeModel.cpp | 105 +++++--
HPPA/TaskTreeModel.h | 11 +
HPPA/TimedDataCollection.cpp | 40 ++-
HPPA/TimedDataCollection.h | 1 +
HPPA/TimedDataCollectionDataStructures.cpp | 73 +++--
HPPA/TimedDataCollectionDataStructures.h | 21 +-
HPPA/TimedDataCollection_ui.ui | 62 ++--
HPPA/TwoMotorControl.cpp | 124 +-------
HPPA/TwoMotorControl.h | 2 +
15 files changed, 626 insertions(+), 223 deletions(-)
create mode 100644 HPPA/PathLine.cpp
create mode 100644 HPPA/PathLine.h
diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp
index 0ddf492..a1c78b5 100644
--- a/HPPA/HPPA.cpp
+++ b/HPPA/HPPA.cpp
@@ -576,7 +576,7 @@ HPPA::HPPA(QWidget* parent)
initMapTools();
//定时采集
- initTimedDataCollection();
+ connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection()));
QString strPath = QCoreApplication::applicationDirPath() + "/UILayout.ini";
QFile file(strPath);
@@ -593,22 +593,26 @@ HPPA::HPPA(QWidget* parent)
void HPPA::initTimedDataCollection()
{
- connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection()));
- mTimedDataCollectionWindow = new TimedDataCollection();
+ TimedDataCollection mTimedDataCollectionWindow;
+
+ m_tmc->onConnectMotor();
// 定时采集控制器 → 相机/马达
- connect(mTimedDataCollectionWindow, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm);
- connect(mTimedDataCollectionWindow, &TimedDataCollection::camParm, this, &HPPA::setTimedDataCollectionCamParm);
- connect(mTimedDataCollectionWindow, &TimedDataCollection::motorParm, this, &HPPA::setTimedDataCollectionMotorParm);
- connect(mTimedDataCollectionWindow, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::camParm, this, &HPPA::setTimedDataCollectionCamParm);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::motorParm, this, &HPPA::setTimedDataCollectionMotorParm);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection);
- connect(mTimedDataCollectionWindow, &TimedDataCollection::switchHalogenLampSignal, m_pc3D, &PowerControl3D::switchHalogenLampPower);
- connect(mTimedDataCollectionWindow, &TimedDataCollection::switchD65LampSignal, m_pc3D, &PowerControl3D::switchD65LampPower);
- connect(mTimedDataCollectionWindow, &TimedDataCollection::switchSlrSignal, m_pc3D, &PowerControl3D::switchSlrPower);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::switchHalogenLampSignal, m_pc3D, &PowerControl3D::switchHalogenLampPower);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::switchD65LampSignal, m_pc3D, &PowerControl3D::switchD65LampPower);
+ connect(&mTimedDataCollectionWindow, &TimedDataCollection::switchSlrSignal, m_pc3D, &PowerControl3D::switchSlrPower);
// 相机/马达 → 定时采集控制器
- connect(m_tmc, &TwoMotorControl::sequenceComplete, mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted);
- connect(m_tmc, &TwoMotorControl::back2OriginSignal_TimedDataCollection, mTimedDataCollectionWindow, &TimedDataCollection::onBack2Origin);
+ connect(m_tmc, &TwoMotorControl::sequenceComplete, &mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted);
+ connect(m_tmc, &TwoMotorControl::back2OriginSignal_TimedDataCollection, &mTimedDataCollectionWindow, &TimedDataCollection::onBack2Origin);
+
+ mTimedDataCollectionWindow.show();
+ mTimedDataCollectionWindow.exec();
}
void HPPA::setTimedDataCollectionHyperCamParm(int camType, double f, double e, QString filePath, QString fileName)
@@ -716,8 +720,7 @@ void HPPA::onTimedDataCollection()
QString checkedScenarioName = checkedScenario->objectName();
if (checkedScenarioName == "mAction3DPlantPhenotypeScenario")//计划采集
{
- mTimedDataCollectionWindow->show();
- //mTimedDataCollectionWindow->exec();
+ initTimedDataCollection();
return;
}
diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h
index 19b1f28..90a24c7 100644
--- a/HPPA/HPPA.h
+++ b/HPPA/HPPA.h
@@ -321,7 +321,6 @@ private:
bool showResultMessageBox(QString title, QString msg);
void disconnectImagerAndCleanup();
- TimedDataCollection* mTimedDataCollectionWindow;
void initTimedDataCollection();
public Q_SLOTS:
diff --git a/HPPA/HPPA.vcxproj b/HPPA/HPPA.vcxproj
index 9f13fa9..bab3e65 100644
--- a/HPPA/HPPA.vcxproj
+++ b/HPPA/HPPA.vcxproj
@@ -140,6 +140,7 @@
+
@@ -252,6 +253,7 @@
+
diff --git a/HPPA/HPPA.vcxproj.filters b/HPPA/HPPA.vcxproj.filters
index 4ccbd4e..d9c467b 100644
--- a/HPPA/HPPA.vcxproj.filters
+++ b/HPPA/HPPA.vcxproj.filters
@@ -250,6 +250,9 @@
Source Files
+
+ Source Files
+
@@ -467,6 +470,9 @@
Header Files
+
+ Header Files
+
diff --git a/HPPA/PathLine.cpp b/HPPA/PathLine.cpp
new file mode 100644
index 0000000..e4ffaa4
--- /dev/null
+++ b/HPPA/PathLine.cpp
@@ -0,0 +1,319 @@
+#include "PathLine.h"
+#include
+#include
+
+PathLineManager::PathLineManager()
+{
+}
+
+PathLineManager::~PathLineManager()
+{
+}
+
+QVector PathLineManager::readFromTableWidget(QTableWidget* tableWidget)
+{
+ QVector pathLines;
+
+ if (tableWidget == nullptr)
+ return pathLines;
+
+ int rowCount = tableWidget->rowCount();
+
+ for (int i = 0; i < rowCount; i++)
+ {
+ PathLine2 tmp;
+
+ tmp.targetYPosition = tableWidget->item(i, 0)->text().toDouble();
+ tmp.speedTargetYPosition = tableWidget->item(i, 1)->text().toDouble();
+ tmp.targetXMinPosition = tableWidget->item(i, 2)->text().toDouble();
+ tmp.speedTargetXMinPosition = tableWidget->item(i, 3)->text().toDouble();
+ tmp.targetXMaxPosition = tableWidget->item(i, 4)->text().toDouble();
+ tmp.speedTargetXMaxPosition = tableWidget->item(i, 5)->text().toDouble();
+
+ pathLines.append(tmp);
+ }
+
+ return pathLines;
+}
+
+void PathLineManager::writeToTableWidget(QTableWidget* tableWidget, const QVector& pathLines)
+{
+ if (tableWidget == nullptr)
+ return;
+
+ // 清空现有行
+ int rowCount = tableWidget->rowCount();
+ for (int i = 0; i < rowCount; i++)
+ {
+ tableWidget->removeRow(0);
+ }
+
+ // 添加新行
+ for (int i = 0; i < pathLines.size(); i++)
+ {
+ tableWidget->insertRow(i);
+
+ QTableWidgetItem* item0 = new QTableWidgetItem(QString::number(pathLines[i].targetYPosition, 'f', 5));
+ QTableWidgetItem* item1 = new QTableWidgetItem(QString::number(pathLines[i].speedTargetYPosition, 'f', 5));
+ QTableWidgetItem* item2 = new QTableWidgetItem(QString::number(pathLines[i].targetXMinPosition, 'f', 5));
+ QTableWidgetItem* item3 = new QTableWidgetItem(QString::number(pathLines[i].speedTargetXMinPosition, 'f', 5));
+ QTableWidgetItem* item4 = new QTableWidgetItem(QString::number(pathLines[i].targetXMaxPosition, 'f', 5));
+ QTableWidgetItem* item5 = new QTableWidgetItem(QString::number(pathLines[i].speedTargetXMaxPosition, 'f', 5));
+
+ item0->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+
+ tableWidget->setItem(i, 0, item0);
+ tableWidget->setItem(i, 1, item1);
+ tableWidget->setItem(i, 2, item2);
+ tableWidget->setItem(i, 3, item3);
+ tableWidget->setItem(i, 4, item4);
+ tableWidget->setItem(i, 5, item5);
+ }
+}
+
+bool PathLineManager::saveToFile(const QString& filePath, QTableWidget* tableWidget)
+{
+ if (tableWidget == nullptr || tableWidget->rowCount() <= 0)
+ return false;
+
+ FILE* fileHandle = fopen(filePath.toStdString().c_str(), "wb+");
+ if (fileHandle == nullptr)
+ return false;
+
+ double number = tableWidget->rowCount() * tableWidget->columnCount();
+ fwrite(&number, sizeof(double), 1, fileHandle);
+
+ double* data = new double[static_cast(number)];
+
+ for (int i = 0; i < tableWidget->rowCount(); i++)
+ {
+ for (int j = 0; j < tableWidget->columnCount(); j++)
+ {
+ data[i * tableWidget->columnCount() + j] = tableWidget->item(i, j)->text().toDouble();
+ }
+ }
+
+ fwrite(data, sizeof(double), static_cast(number), fileHandle);
+
+ fclose(fileHandle);
+ delete[] data;
+
+ return true;
+}
+
+bool PathLineManager::saveToFile(const QString& filePath, const QVector& pathLines)
+{
+ if (pathLines.isEmpty())
+ return false;
+
+ FILE* fileHandle = fopen(filePath.toStdString().c_str(), "wb+");
+ if (fileHandle == nullptr)
+ return false;
+
+ double number = pathLines.size() * COLUMN_COUNT;
+ fwrite(&number, sizeof(double), 1, fileHandle);
+
+ double* data = new double[static_cast(number)];
+
+ for (int i = 0; i < pathLines.size(); i++)
+ {
+ data[i * COLUMN_COUNT + 0] = pathLines[i].targetYPosition;
+ data[i * COLUMN_COUNT + 1] = pathLines[i].speedTargetYPosition;
+ data[i * COLUMN_COUNT + 2] = pathLines[i].targetXMinPosition;
+ data[i * COLUMN_COUNT + 3] = pathLines[i].speedTargetXMinPosition;
+ data[i * COLUMN_COUNT + 4] = pathLines[i].targetXMaxPosition;
+ data[i * COLUMN_COUNT + 5] = pathLines[i].speedTargetXMaxPosition;
+ }
+
+ fwrite(data, sizeof(double), static_cast(number), fileHandle);
+
+ fclose(fileHandle);
+ delete[] data;
+
+ return true;
+}
+
+bool PathLineManager::readFromFile(const QString& filePath, QTableWidget* tableWidget)
+{
+ if (tableWidget == nullptr)
+ return false;
+
+ FILE* fileHandle = fopen(filePath.toStdString().c_str(), "rb");
+ if (fileHandle == nullptr)
+ return false;
+
+ double number;
+ fread(&number, sizeof(double), 1, fileHandle);
+
+ double* data = new double[static_cast(number)];
+ for (int i = 0; i < static_cast(number); i++)
+ {
+ fread(data + i, sizeof(double), 1, fileHandle);
+ }
+
+ // 清空现有行
+ int rowCount = tableWidget->rowCount();
+ for (int i = 0; i < rowCount; i++)
+ {
+ tableWidget->removeRow(0);
+ }
+
+ // 添加新行
+ int recordLineCount = static_cast(number) / tableWidget->columnCount();
+ for (int i = 0; i < recordLineCount; i++)
+ {
+ tableWidget->insertRow(i);
+ }
+
+ // 填充数据
+ for (int i = 0; i < tableWidget->rowCount(); i++)
+ {
+ for (int j = 0; j < tableWidget->columnCount(); j++)
+ {
+ QTableWidgetItem* tmp = new QTableWidgetItem(
+ QString::number(data[i * tableWidget->columnCount() + j], 'f', 5));
+ tmp->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ tableWidget->setItem(i, j, tmp);
+ }
+ }
+
+ fclose(fileHandle);
+ delete[] data;
+
+ return true;
+}
+
+QVector PathLineManager::readFromFile(const QString& filePath, bool* success)
+{
+ QVector pathLines;
+
+ FILE* fileHandle = fopen(filePath.toStdString().c_str(), "rb");
+ if (fileHandle == nullptr)
+ {
+ if (success) *success = false;
+ return pathLines;
+ }
+
+ double number;
+ fread(&number, sizeof(double), 1, fileHandle);
+
+ double* data = new double[static_cast(number)];
+ for (int i = 0; i < static_cast(number); i++)
+ {
+ fread(data + i, sizeof(double), 1, fileHandle);
+ }
+
+ int recordLineCount = static_cast(number) / COLUMN_COUNT;
+ for (int i = 0; i < recordLineCount; i++)
+ {
+ PathLine2 tmp;
+ tmp.targetYPosition = data[i * COLUMN_COUNT + 0];
+ tmp.speedTargetYPosition = data[i * COLUMN_COUNT + 1];
+ tmp.targetXMinPosition = data[i * COLUMN_COUNT + 2];
+ tmp.speedTargetXMinPosition = data[i * COLUMN_COUNT + 3];
+ tmp.targetXMaxPosition = data[i * COLUMN_COUNT + 4];
+ tmp.speedTargetXMaxPosition = data[i * COLUMN_COUNT + 5];
+
+ pathLines.append(tmp);
+ }
+
+ fclose(fileHandle);
+ delete[] data;
+
+ if (success) *success = true;
+ return pathLines;
+}
+
+void PathLineManager::addRecordLine(QTableWidget* tableWidget,
+ double yPos, double ySpeed,
+ double xMinPos, double xMinSpeed,
+ double xMaxPos, double xMaxSpeed)
+{
+ if (tableWidget == nullptr)
+ return;
+
+ int currentRow = tableWidget->currentRow();
+ int insertRow = (currentRow == -1) ? tableWidget->rowCount() : currentRow + 1;
+
+ tableWidget->insertRow(insertRow);
+
+ QTableWidgetItem* item0 = new QTableWidgetItem(QString::number(yPos, 'f', 2));
+ QTableWidgetItem* item1 = new QTableWidgetItem(QString::number(ySpeed, 'f', 2));
+ QTableWidgetItem* item2 = new QTableWidgetItem(QString::number(xMinPos, 'f', 2));
+ QTableWidgetItem* item3 = new QTableWidgetItem(QString::number(xMinSpeed, 'f', 2));
+ QTableWidgetItem* item4 = new QTableWidgetItem(QString::number(xMaxPos, 'f', 2));
+ QTableWidgetItem* item5 = new QTableWidgetItem(QString::number(xMaxSpeed, 'f', 2));
+
+ item0->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+
+ tableWidget->setItem(insertRow, 0, item0);
+ tableWidget->setItem(insertRow, 1, item1);
+ tableWidget->setItem(insertRow, 2, item2);
+ tableWidget->setItem(insertRow, 3, item3);
+ tableWidget->setItem(insertRow, 4, item4);
+ tableWidget->setItem(insertRow, 5, item5);
+}
+
+double PathLineManager::calculateTimeFromFile(const QString& filePath)
+{
+ bool success = false;
+ QVector pathLines = readFromFile(filePath, &success);
+ if (!success || pathLines.isEmpty())
+ return 0.0;
+
+ double totalTimeSecond = 0.0;
+ double currentX = 0.0;
+ double currentY = 0.0;
+ double yTime;
+ double xTime;
+
+ for (int i = 0; i < pathLines.size(); i++)
+ {
+ const PathLine2& line = pathLines[i];
+
+ double yDistance = qAbs(line.targetYPosition - currentY);
+ if (line.speedTargetYPosition > 0.0 && yDistance > 0.0)
+ {
+ yTime = yDistance / line.speedTargetYPosition;
+ }
+ double xMinDistance = qAbs(line.targetXMinPosition - currentX);
+ if (line.speedTargetXMinPosition > 0.0 && xMinDistance > 0.0)
+ {
+ xTime = xMinDistance / line.speedTargetXMinPosition;
+ }
+ totalTimeSecond += std::max(yTime, xTime);
+
+ double xMaxDistance = qAbs(line.targetXMaxPosition - line.targetXMinPosition);
+ if (line.speedTargetXMaxPosition > 0.0 && xMaxDistance > 0.0)
+ {
+ totalTimeSecond += xMaxDistance / line.speedTargetXMaxPosition;
+ }
+
+ currentX = line.targetXMaxPosition;
+ currentY = line.targetYPosition;
+ }
+
+ double returnYDistance = currentY;
+ double returnXDistance = currentX;
+ if (currentY > 0.0)
+ {
+ yTime += returnYDistance / pathLines[0].speedTargetYPosition;
+ }
+ if (currentX > 0.0)
+ {
+ xTime += returnXDistance / pathLines[0].speedTargetXMinPosition;
+ }
+ totalTimeSecond += std::max(yTime, xTime);
+
+ return totalTimeSecond / 60;
+}
diff --git a/HPPA/PathLine.h b/HPPA/PathLine.h
new file mode 100644
index 0000000..e037aac
--- /dev/null
+++ b/HPPA/PathLine.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include
+#include
+#include
+
+// PathLine 结构体定义(如果还没有在其他地方定义)
+struct PathLine2
+{
+ double targetYPosition;
+ double speedTargetYPosition;
+ double targetXMinPosition;
+ double speedTargetXMinPosition;
+ double targetXMaxPosition;
+ double speedTargetXMaxPosition;
+};
+
+class PathLineManager
+{
+public:
+ PathLineManager();
+ ~PathLineManager();
+
+ // 从TableWidget读取PathLine数据
+ static QVector readFromTableWidget(QTableWidget* tableWidget);
+
+ // 将PathLine数据写入TableWidget
+ static void writeToTableWidget(QTableWidget* tableWidget, const QVector& pathLines);
+
+ // 保存PathLine到文件
+ static bool saveToFile(const QString& filePath, QTableWidget* tableWidget);
+ static bool saveToFile(const QString& filePath, const QVector& pathLines);
+
+ // 从文件读取PathLine
+ static bool readFromFile(const QString& filePath, QTableWidget* tableWidget);
+ static QVector readFromFile(const QString& filePath, bool* success = nullptr);
+
+ // 添加一行PathLine到TableWidget
+ static void addRecordLine(QTableWidget* tableWidget,
+ double yPos = 15.0,
+ double ySpeed = 1.0,
+ double xMinPos = 0.0,
+ double xMinSpeed = 1.0,
+ double xMaxPos = 50.0,
+ double xMaxSpeed = 1.0);
+
+ static double calculateTimeFromFile(const QString& filePath);
+
+private:
+ static const int COLUMN_COUNT = 6;
+};
diff --git a/HPPA/TaskTreeModel.cpp b/HPPA/TaskTreeModel.cpp
index 87d76f1..5443bc9 100644
--- a/HPPA/TaskTreeModel.cpp
+++ b/HPPA/TaskTreeModel.cpp
@@ -50,12 +50,16 @@ TreeNode* TreeNode::parentNode()
TaskTreeModel::TaskTreeModel(QObject* parent)
: QAbstractItemModel(parent)
, m_rootNode(new TreeNode())
+ , m_countdownTimer(new QTimer(this))
{
m_rootNode->nodeType = TreeNodeType::Root;
+ m_countdownTimer->setInterval(1000);
+ connect(m_countdownTimer, &QTimer::timeout, this, &TaskTreeModel::onCountdownTimerTimeout);
}
TaskTreeModel::~TaskTreeModel()
{
+ m_countdownTimer->stop();
delete m_rootNode;
}
@@ -123,6 +127,18 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const
return QString::fromLocal8Bit("定时任务 %1").arg(task.id);
case ColScheduledTime:
return task.scheduledTime.toString("yyyy-MM-dd HH:mm:ss");
+ case ColCountdown: {
+ if (task.status == TaskStatus::Finished || task.status == TaskStatus::Running)
+ {
+ return QString::fromLocal8Bit("0");
+ }
+ qint64 seconds = QDateTime::currentDateTime().secsTo(task.scheduledTime);
+ if (seconds < 0)
+ {
+ return QString::fromLocal8Bit("已超时");
+ }
+ return formatCountdown(seconds);
+ }
case ColStartTime:
return task.startTime.isValid() ?
task.startTime.toString("HH:mm:ss") : "-";
@@ -131,6 +147,8 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const
task.endTime.toString("HH:mm:ss") : "-";
case ColDuration:
return formatDuration(task.durationMinutes);
+ case ColEstimatedDuration:
+ return formatDuration(task.estimatedDurationMinutes);
case ColStatus:
return statusToString(task.status);
case ColProgress: {
@@ -151,6 +169,8 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const
return subTaskTypeToString(subTask.type);
case ColScheduledTime:
return "-";
+ case ColCountdown:
+ return "-";
case ColStartTime:
return subTask.startTime.isValid() ?
subTask.startTime.toString("HH:mm:ss") : "-";
@@ -159,6 +179,8 @@ QVariant TaskTreeModel::data(const QModelIndex& index, int role) const
subTask.endTime.toString("HH:mm:ss") : "-";
case ColDuration:
return formatDuration(subTask.durationMinutes);
+ case ColEstimatedDuration:
+ return formatDuration(subTask.estimatedDurationMinutes);
case ColStatus:
return statusToString(subTask.status);
case ColProgress:
@@ -265,9 +287,11 @@ QVariant TaskTreeModel::headerData(int section, Qt::Orientation orientation, int
switch (section) {
case ColName: return QString::fromLocal8Bit("名称");
case ColScheduledTime: return QString::fromLocal8Bit("计划时间");
+ case ColCountdown: return QString::fromLocal8Bit("倒计时");
case ColStartTime: return QString::fromLocal8Bit("开始时间");
case ColEndTime: return QString::fromLocal8Bit("结束时间");
case ColDuration: return QString::fromLocal8Bit("耗时");
+ case ColEstimatedDuration: return QString::fromLocal8Bit("预测耗时");
case ColStatus: return QString::fromLocal8Bit("状态");
case ColProgress: return QString::fromLocal8Bit("进度");
case ColPath: return QString::fromLocal8Bit("路径");
@@ -285,6 +309,8 @@ Qt::ItemFlags TaskTreeModel::flags(const QModelIndex& index) const
void TaskTreeModel::setTasks(const QVector& tasks)
{
+ m_countdownTimer->stop();
+
beginResetModel();
m_tasks = tasks;
@@ -292,6 +318,8 @@ void TaskTreeModel::setTasks(const QVector& tasks)
setupModelData();
endResetModel();
+
+ m_countdownTimer->start();
}
void TaskTreeModel::setupModelData()
@@ -400,6 +428,19 @@ void TaskTreeModel::updateSubTask(int taskId, int subTaskIndex, const SubTask& s
emit subTaskUpdated(taskId, subTaskIndex);
}
+void TaskTreeModel::setTaskAndSubtaskStatus(int taskId, TaskStatus status)
+{
+ int dataIndex = findTaskDataIndex(taskId);
+ if (dataIndex < 0) return;
+
+ updateTaskStatus(taskId, status);
+
+ for (size_t i = 0; i < m_tasks[dataIndex].subTaskCount(); i++)
+ {
+ updateSubTaskStatus(taskId, i, status);
+ }
+}
+
void TaskTreeModel::updateTaskStatus(int taskId, TaskStatus status)
{
int dataIndex = findTaskDataIndex(taskId);
@@ -407,17 +448,6 @@ void TaskTreeModel::updateTaskStatus(int taskId, TaskStatus status)
m_tasks[dataIndex].status = status;
- if (status == TaskStatus::Running) {
- m_tasks[dataIndex].startTime = QDateTime::currentDateTime();
- }
- else if (status == TaskStatus::Finished) {
- m_tasks[dataIndex].endTime = QDateTime::currentDateTime();
- if (m_tasks[dataIndex].startTime.isValid()) {
- m_tasks[dataIndex].durationMinutes =
- m_tasks[dataIndex].startTime.secsTo(m_tasks[dataIndex].endTime) / 60.0;
- }
- }
-
QModelIndex taskIndex = getTaskIndex(taskId);
if (taskIndex.isValid()) {
QModelIndex topLeft = index(taskIndex.row(), 0, taskIndex.parent());
@@ -426,6 +456,12 @@ void TaskTreeModel::updateTaskStatus(int taskId, TaskStatus status)
}
}
+void TaskTreeModel::updateSubTaskStatusAndProgress(int taskId, int subTaskIndex, TaskStatus status)
+{
+ updateSubTaskStatus(taskId, subTaskIndex, status);
+ updateProgress(taskId);
+}
+
void TaskTreeModel::updateSubTaskStatus(int taskId, int subTaskIndex, TaskStatus status)
{
int dataIndex = findTaskDataIndex(taskId);
@@ -435,23 +471,16 @@ void TaskTreeModel::updateSubTaskStatus(int taskId, int subTaskIndex, TaskStatus
SubTask& subTask = m_tasks[dataIndex].subTasks[subTaskIndex];
subTask.status = status;
- if (status == TaskStatus::Running) {
- subTask.startTime = QDateTime::currentDateTime();
- }
- else if (status == TaskStatus::Finished) {
- subTask.endTime = QDateTime::currentDateTime();
- if (subTask.startTime.isValid()) {
- subTask.durationMinutes = subTask.startTime.secsTo(subTask.endTime) / 60.0;
- }
- }
-
QModelIndex subTaskModelIndex = getSubTaskIndex(taskId, subTaskIndex);
if (subTaskModelIndex.isValid()) {
QModelIndex topLeft = index(subTaskModelIndex.row(), 0, subTaskModelIndex.parent());
QModelIndex bottomRight = index(subTaskModelIndex.row(), ColumnCount - 1, subTaskModelIndex.parent());
emit dataChanged(topLeft, bottomRight);
}
+}
+void TaskTreeModel::updateProgress(int taskId)
+{
// 更新父任务进度
QModelIndex taskIndex = getTaskIndex(taskId);
if (taskIndex.isValid()) {
@@ -534,12 +563,14 @@ int TaskTreeModel::findTaskDataIndex(int taskId) const
QString TaskTreeModel::statusToString(TaskStatus status) const
{
switch (status) {
+ case TaskStatus::default: return QString::fromLocal8Bit("未调度");
case TaskStatus::Waiting: return QString::fromLocal8Bit("等待中");
case TaskStatus::Running: return QString::fromLocal8Bit("运行中");
case TaskStatus::Finished: return QString::fromLocal8Bit("已完成");
case TaskStatus::Skiped: return QString::fromLocal8Bit("已跳过");
+ case TaskStatus::Timeout: return QString::fromLocal8Bit("超时");
}
- return "未知";
+ return "";
}
QString TaskTreeModel::subTaskTypeToString(SubTaskType type) const
@@ -582,3 +613,33 @@ QColor TaskTreeModel::statusColor(TaskStatus status) const
}
return QColor(255, 255, 255);
}
+
+QString TaskTreeModel::formatCountdown(qint64 seconds) const
+{
+ if (seconds < 0) {
+ return QString::fromLocal8Bit("已超时");
+ }
+
+ int hours = static_cast(seconds) / 3600;
+ int mins = (static_cast(seconds) % 3600) / 60;
+ int secs = static_cast(seconds) % 60;
+
+ return QString("%1:%2:%3")
+ .arg(hours, 2, 10, QChar('0'))
+ .arg(mins, 2, 10, QChar('0'))
+ .arg(secs, 2, 10, QChar('0'));
+}
+
+void TaskTreeModel::onCountdownTimerTimeout()
+{
+ for (int i = 0; i < m_tasks.size(); ++i)
+ {
+ const TimedTask& task = m_tasks[i];
+ QModelIndex taskIndex = getTaskIndex(task.id);
+ if (taskIndex.isValid())
+ {
+ QModelIndex countdownIndex = index(taskIndex.row(), ColCountdown, taskIndex.parent());
+ emit dataChanged(countdownIndex, countdownIndex);
+ }
+ }
+}
diff --git a/HPPA/TaskTreeModel.h b/HPPA/TaskTreeModel.h
index e60ed38..d9e762a 100644
--- a/HPPA/TaskTreeModel.h
+++ b/HPPA/TaskTreeModel.h
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include "TimedDataCollectionDataStructures.h"
// 树节点类型
@@ -47,9 +48,11 @@ public:
enum Column {
ColName = 0, // 任务名称/子任务类型
ColScheduledTime, // 计划时间
+ ColCountdown, // 倒计时
ColStartTime, // 开始时间
ColEndTime, // 结束时间
ColDuration, // 耗时
+ ColEstimatedDuration, // 预测耗时
ColStatus, // 状态
ColProgress, // 进度(仅任务有效)
ColPath, // 路径
@@ -73,7 +76,10 @@ public:
void updateTask(const TimedTask& task);
void updateSubTask(int taskId, int subTaskIndex, const SubTask& subTask);
void updateTaskStatus(int taskId, TaskStatus status);
+ void setTaskAndSubtaskStatus(int taskId, TaskStatus status);
+ void updateSubTaskStatusAndProgress(int taskId, int subTaskIndex, TaskStatus status);
void updateSubTaskStatus(int taskId, int subTaskIndex, TaskStatus status);
+ void updateProgress(int taskId);
// 获取数据
QVector& tasks() { return m_tasks; }
@@ -89,6 +95,9 @@ signals:
void taskUpdated(int taskId);
void subTaskUpdated(int taskId, int subTaskIndex);
+private slots:
+ void onCountdownTimerTimeout();
+
private:
void setupModelData();
void clearTree();
@@ -100,7 +109,9 @@ private:
QString subTaskTypeToString(SubTaskType type) const;
QString formatDuration(double minutes) const;
QColor statusColor(TaskStatus status) const;
+ QString formatCountdown(qint64 seconds) const;
TreeNode* m_rootNode;
QVector m_tasks;
+ QTimer* m_countdownTimer;
};
diff --git a/HPPA/TimedDataCollection.cpp b/HPPA/TimedDataCollection.cpp
index f21f85a..cb8f9e0 100644
--- a/HPPA/TimedDataCollection.cpp
+++ b/HPPA/TimedDataCollection.cpp
@@ -52,9 +52,11 @@ void TimedDataCollection::setupUI()
// 设置列宽
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColName, 200);
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColScheduledTime, 150);
+ ui.taskTreeView->setColumnWidth(TaskTreeModel::ColCountdown, 100);
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColStartTime, 100);
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColEndTime, 100);
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColDuration, 100);
+ ui.taskTreeView->setColumnWidth(TaskTreeModel::ColEstimatedDuration, 100);
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColStatus, 100);
ui.taskTreeView->setColumnWidth(TaskTreeModel::ColProgress, 80);
@@ -167,7 +169,7 @@ void TimedDataCollection::onSubTaskStarted(int taskId, int subTaskIndex)
{
m_currentSubTaskIndex = subTaskIndex;
- m_taskModel->updateSubTaskStatus(taskId, subTaskIndex, TaskStatus::Running);
+ m_taskModel->updateSubTaskStatusAndProgress(taskId, subTaskIndex, TaskStatus::Running);
// 滚动到当前子任务
QModelIndex subTaskIndex_model = m_taskModel->getSubTaskIndex(taskId, subTaskIndex);
@@ -182,7 +184,7 @@ void TimedDataCollection::onSubTaskStarted(int taskId, int subTaskIndex)
void TimedDataCollection::onSubTaskFinished(int taskId, int subTaskIndex)
{
- m_taskModel->updateSubTaskStatus(taskId, subTaskIndex, TaskStatus::Finished);
+ m_taskModel->updateSubTaskStatusAndProgress(taskId, subTaskIndex, TaskStatus::Finished);
updateStatusBar();
emit subTaskFinished(taskId, subTaskIndex);
@@ -396,11 +398,30 @@ void TimedDataCollection::readTimedTaskFromFile(const QString& filePath)
if (TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(filePath, loadedTasks)) {
qDebug() << "Tasks loaded successfully, count:" << loadedTasks.size();
+ // 预测耗时:计算每个子任务和整个任务的预计耗时
+ for (int i = 0; i < loadedTasks.size(); ++i)
+ {
+ double totalEstimatedMinutes = 0.0;
+ for (int j = 0; j < loadedTasks[i].subTasks.size(); ++j)
+ {
+ QString pathLineFilePath = loadedTasks[i].subTasks[j].pathLineFilePath;
+ if (!pathLineFilePath.isEmpty())
+ {
+ double estimatedMinutes = PathLineManager::calculateTimeFromFile(pathLineFilePath);
+ loadedTasks[i].subTasks[j].estimatedDurationMinutes = estimatedMinutes;
+ totalEstimatedMinutes += loadedTasks[i].subTasks[j].estimatedDurationMinutes;
+ }
+ }
+ double slrTimeMinute = 135 / 60;
+ loadedTasks[i].estimatedDurationMinutes = totalEstimatedMinutes + loadedTasks[i].HalogenLampPreheatingTime_Minute + slrTimeMinute;
+ }
+
m_taskModel->setTasks(loadedTasks);
ui.taskTreeView->expandAll(); // 默认展开所有任务
// 更新调度器
- if (m_scheduler) {
+ if (m_scheduler)
+ {
m_scheduler->loadTasks(loadedTasks);
}
@@ -415,7 +436,18 @@ void TimedDataCollection::readTimedTaskFromFile(const QString& filePath)
void TimedDataCollection::startScheduler()
{
- if (m_scheduler) {
+ if (m_scheduler)
+ {
+ if (m_scheduler->isRunning())
+ {
+ return;
+ }
+
+ for (size_t i = 0; i < m_taskModel->tasks().size(); i++)
+ {
+ m_taskModel->setTaskAndSubtaskStatus(m_taskModel->tasks()[i].id, TaskStatus::Waiting);
+ }
+
m_scheduler->loadTasks(m_taskModel->tasks());
m_scheduler->start();
diff --git a/HPPA/TimedDataCollection.h b/HPPA/TimedDataCollection.h
index 6faa2d7..7b45c98 100644
--- a/HPPA/TimedDataCollection.h
+++ b/HPPA/TimedDataCollection.h
@@ -7,6 +7,7 @@
#include "ui_TimedDataCollection_ui.h"
#include "TimedDataCollectionDataStructures.h"
#include "TaskTreeModel.h"
+#include "PathLine.h"
class TimedDataCollection : public QDialog
{
diff --git a/HPPA/TimedDataCollectionDataStructures.cpp b/HPPA/TimedDataCollectionDataStructures.cpp
index 2d9d30f..c376411 100644
--- a/HPPA/TimedDataCollectionDataStructures.cpp
+++ b/HPPA/TimedDataCollectionDataStructures.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
// ==================== 公共接口实现 ====================
@@ -88,9 +89,9 @@ QString TimedDataCollectionDataStructuresReaderWriter::taskStatusToString(TaskSt
TaskStatus TimedDataCollectionDataStructuresReaderWriter::stringToTaskStatus(const QString& str)
{
- if (str == "Running") return TaskStatus::Running;
- if (str == "Finished") return TaskStatus::Finished;
- return TaskStatus::Waiting;
+ //if (str == "Running") return TaskStatus::Running;
+ //if (str == "Finished") return TaskStatus::Finished;
+ return TaskStatus::default;
}
QString TimedDataCollectionDataStructuresReaderWriter::subTaskTypeToString(SubTaskType type)
@@ -135,8 +136,8 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const S
bool TimedDataCollectionDataStructuresReaderWriter::jsonToSubTask(const QJsonObject& json, SubTask& subTask)
{
subTask.type = stringToSubTaskType(json["type"].toString());
- subTask.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
- subTask.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
+ subTask.startTime = QDateTime::fromString(QString(), Qt::ISODate);
+ subTask.endTime = QDateTime::fromString(QString(), Qt::ISODate);
subTask.durationMinutes = json["durationMinutes"].toDouble();
subTask.estimatedDurationMinutes = json["estimatedDurationMinutes"].toDouble();
subTask.pathLineFilePath = json["pathLineFilePath"].toString();
@@ -158,6 +159,7 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const
obj["startTime"] = task.startTime.toString(Qt::ISODate);
obj["endTime"] = task.endTime.toString(Qt::ISODate);
obj["durationMinutes"] = task.durationMinutes;
+ obj["estimatedDurationMinutes"] = task.estimatedDurationMinutes;
obj["savePath"] = task.savePath;
obj["status"] = taskStatusToString(task.status);
obj["HalogenLampPreheatingTime_Minute"] = task.HalogenLampPreheatingTime_Minute;
@@ -175,9 +177,10 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonO
{
task.id = json["id"].toInt();
task.scheduledTime = QDateTime::fromString(json["scheduledTime"].toString(), Qt::ISODate);
- task.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
- task.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
+ task.startTime = QDateTime::fromString(QString(), Qt::ISODate);
+ task.endTime = QDateTime::fromString(QString(), Qt::ISODate);
task.durationMinutes = json["durationMinutes"].toDouble();
+ task.estimatedDurationMinutes = json["estimatedDurationMinutes"].toDouble();
task.savePath = json["savePath"].toString();
task.status = stringToTaskStatus(json["status"].toString());
task.HalogenLampPreheatingTime_Minute = json["HalogenLampPreheatingTime_Minute"].toDouble();
@@ -220,6 +223,10 @@ void TaskExecutor::execute(const TimedTask& task)
m_task = task;
m_task.startTime = QDateTime::currentDateTime();
+ m_task.status = TaskStatus::Running;
+
+ emit taskUpdated(m_task);
+
m_currentSubTaskIndex = 0;
m_isRunning = true;
@@ -293,6 +300,7 @@ void TaskExecutor::onSequenceComplete(int status)
qDebug() << "TaskExecutor: subtask "<< m_currentSubTaskIndex<< " time consuming(Minutes): "<< subTask.durationMinutes;
emit subTaskFinished(m_currentSubTaskIndex, subTask.type, (status == 0));
+ emit taskUpdated(m_task);
}
//
@@ -315,6 +323,8 @@ void TaskExecutor::onSequenceComplete(int status)
int nestSubTaskIndex = m_currentSubTaskIndex + 1;
if (nestSubTaskIndex >= m_task.subTasks.size())
{
+ emit switchD65LampSignal(0);
+ emit switchSlrSignal(0);
emit switchHalogenLampSignal(0);
return;
}
@@ -501,24 +511,53 @@ void TaskScheduler::stop()
void TaskScheduler::checkTasks()
{
+ // 检查是否所有任务都不需要执行
+ bool allTasksDone = std::all_of(m_tasks.begin(), m_tasks.end(),
+ [](const TimedTask& task) {
+ return task.status != TaskStatus::Waiting;
+ });
+
+ if (allTasksDone)
+ {
+ std::cerr << "TaskScheduler::checkTasks,没有任务等待执行,停止调度器" << std::endl;
+ stop();
+ }
+
QDateTime now = QDateTime::currentDateTime();
- for (auto& task : m_tasks) {
+ if (m_currentTaskId >= 0)//有任务正在执行
+ {
+ return;
+ }
+
+ for (auto& task : m_tasks)
+ {
if (task.status != TaskStatus::Waiting) continue;
- // 超过计划时间1分钟以上,认为任务已过时,跳过
- if (task.scheduledTime.addSecs(60) < now) {
+ // 超过计划时间threSecs,认为任务已过时,跳过
+ qint64 threSecs = 30;
+ if (task.scheduledTime.addSecs(threSecs) < now)
+ {
std::cerr << "TaskScheduler::checkTasks,任务已过时,跳过:" << task.id << std::endl;
- task.status = TaskStatus::Finished;
+ task.status = TaskStatus::Timeout;
+ for (size_t i = 0; i < task.subTaskCount(); i++)
+ {
+ task.subTasks[i].status = TaskStatus::Timeout;
+ }
+
+ emit taskDataChanged(task);
continue;
}
if (task.scheduledTime > now) continue;
- // 到达计划时间,启动任务
- std::cerr << "TaskScheduler::checkTasks,到达计划时间,启动任务" << std::endl;
- executeTask(task);
- break; // 一次只执行一个任务
+ qint64 fireThreSecs = 5;
+ if (task.scheduledTime.addSecs(-1*fireThreSecs) < now && task.scheduledTime.addSecs(fireThreSecs) > now)// 到达计划时间,启动任务
+ {
+ std::cerr << "TaskScheduler::checkTasks,到达计划时间,启动任务" << std::endl;
+ executeTask(task);
+ break; // 一次只执行一个任务
+ }
}
}
@@ -561,10 +600,10 @@ void TaskScheduler::executeTask(TimedTask& task)
{
qDebug() << "TaskScheduler: Executing task" << task.id;
- updateTaskStatus(task.id, TaskStatus::Running);
+ //updateTaskStatus(task.id, TaskStatus::Running);
m_currentTaskId = task.id;
- emit taskStarted(task.id);
+ //emit taskStarted(task.id);
// 创建任务执行器
m_currentExecutor = new TaskExecutor(this);
diff --git a/HPPA/TimedDataCollectionDataStructures.h b/HPPA/TimedDataCollectionDataStructures.h
index 7571707..e03cb82 100644
--- a/HPPA/TimedDataCollectionDataStructures.h
+++ b/HPPA/TimedDataCollectionDataStructures.h
@@ -12,10 +12,12 @@
// 任务状态
enum class TaskStatus {
+ default, //未调度
Waiting, // 等待
Running, // 运行中
Finished, // 结束
- Skiped //跳过
+ Skiped, //跳过
+ Timeout //超时
};
// 子任务类型
@@ -49,14 +51,15 @@ struct SubTask {
// ==================== 定时任务 ====================
struct TimedTask {
- int id = 0; // 任务ID
- QDateTime scheduledTime; // 计划时间
- QDateTime startTime; // 开始时间
- QDateTime endTime; // 结束时间
- double durationMinutes = 0; // 耗时(秒)
- QString savePath; // 数据保存路径
- QVector subTasks; // 子任务列表
- TaskStatus status = TaskStatus::Waiting; // 状态
+ int id = 0;
+ QDateTime scheduledTime;
+ QDateTime startTime;
+ QDateTime endTime;
+ double durationMinutes = 0;
+ double estimatedDurationMinutes = 0;
+ QString savePath;
+ QVector subTasks;
+ TaskStatus status = TaskStatus::Waiting;
double HalogenLampPreheatingTime_Minute;
// 计算所有子任务的预计总时间
diff --git a/HPPA/TimedDataCollection_ui.ui b/HPPA/TimedDataCollection_ui.ui
index 0c33fef..9258d0a 100644
--- a/HPPA/TimedDataCollection_ui.ui
+++ b/HPPA/TimedDataCollection_ui.ui
@@ -13,54 +13,20 @@
Dialog
-
+
-
-
-
-
-
-
-
-
-
-
- -
-
-
- 删除总计划任务
-
-
-
- -
-
-
- 添加子任务
-
-
+
-
-
+
+
+ -
+
- 添加总计划任务
+ ...
- -
-
-
- 删除子任务
-
-
-
- -
-
-
- 停止调度
-
-
-
- -
-
-
-
@@ -68,7 +34,7 @@
- -
+
-
开始调度
@@ -82,6 +48,13 @@
+ -
+
+
+ 停止调度
+
+
+
-
@@ -89,11 +62,14 @@
- -
+
-
TextLabel
+
+ Qt::AlignCenter
+
diff --git a/HPPA/TwoMotorControl.cpp b/HPPA/TwoMotorControl.cpp
index 275558d..9a060ee 100644
--- a/HPPA/TwoMotorControl.cpp
+++ b/HPPA/TwoMotorControl.cpp
@@ -544,51 +544,15 @@ void TwoMotorControl::on_rangeMeasurement()
void TwoMotorControl::onAddRecordLine_btn()
{
- //准备数据:获取y马达的当前位置,获取x马达的当前位置和最大位置
+ // 准备数据:获取y马达的当前位置,获取x马达的当前位置和最大位置
double currentPosOfYmotor = 15;
-
double currentPosOfXmotor = 0;
double maxRangeOfXmotor = 50;
- //获取选中行的索引
- int currentRow = ui.recordLine_tableWidget->currentRow();
- std::cout << "currentRow:" << currentRow << std::endl;
-
- QTableWidgetItem* Item1 = new QTableWidgetItem(QString::number(currentPosOfYmotor, 10, 2));
- QTableWidgetItem* Item2 = new QTableWidgetItem(QString::number(1, 10, 2));
- QTableWidgetItem* Item3 = new QTableWidgetItem(QString::number(currentPosOfXmotor, 10, 2));
- QTableWidgetItem* Item4 = new QTableWidgetItem(QString::number(1, 10, 2));
- QTableWidgetItem* Item5 = new QTableWidgetItem(QString::number(maxRangeOfXmotor, 10, 2));
- QTableWidgetItem* Item6 = new QTableWidgetItem(QString::number(1, 10, 2));
- Item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- Item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- Item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- Item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- Item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- Item6->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- if (currentRow == -1)//当没有选中行时
- {
- int RowCount = ui.recordLine_tableWidget->rowCount();//Returns the number of rows. 从1开始的
- ui.recordLine_tableWidget->insertRow(RowCount);//增加一行,形参是从0开始的
-
- ui.recordLine_tableWidget->setItem(RowCount, 0, Item1);
- ui.recordLine_tableWidget->setItem(RowCount, 1, Item2);
- ui.recordLine_tableWidget->setItem(RowCount, 2, Item3);
- ui.recordLine_tableWidget->setItem(RowCount, 3, Item4);
- ui.recordLine_tableWidget->setItem(RowCount, 4, Item5);
- ui.recordLine_tableWidget->setItem(RowCount, 5, Item6);
- }
- else
- {
- ui.recordLine_tableWidget->insertRow(currentRow + 1);//增加一行,形参是从0开始的
-
- ui.recordLine_tableWidget->setItem(currentRow + 1, 0, Item1);
- ui.recordLine_tableWidget->setItem(currentRow + 1, 1, Item2);
- ui.recordLine_tableWidget->setItem(currentRow + 1, 2, Item3);
- ui.recordLine_tableWidget->setItem(currentRow + 1, 3, Item4);
- ui.recordLine_tableWidget->setItem(currentRow + 1, 4, Item5);
- ui.recordLine_tableWidget->setItem(currentRow + 1, 5, Item6);
- }
+ PathLineManager::addRecordLine(ui.recordLine_tableWidget,
+ currentPosOfYmotor, 1.0,
+ currentPosOfXmotor, 1.0,
+ maxRangeOfXmotor, 1.0);
}
void TwoMotorControl::onRemoveRecordLine_btn()
@@ -609,106 +573,40 @@ void TwoMotorControl::onDeleteRecordLine_btn()
void TwoMotorControl::onSaveRecordLine2File_btn()
{
- //确保采集线存在
+ // 确保采集线存在
if (ui.recordLine_tableWidget->rowCount() <= 0)
{
- QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先生成轨迹!"));
+ QMessageBox::information(this, QString::fromLocal8Bit("提示"),
+ QString::fromLocal8Bit("请先生成轨迹!"));
return;
}
-
FileOperation* fileOperation = new FileOperation();
string directory = fileOperation->getDirectoryOfExe();
-
QString RecordLineFilePath = QFileDialog::getSaveFileName(this, tr("Save RecordLine3 File"),
QString::fromStdString(directory),
tr("RecordLineFile3 (*.RecordLine3)"));
-
if (RecordLineFilePath.isEmpty())
{
return;
}
-
- FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "wb+");
-
- double number = ui.recordLine_tableWidget->rowCount() * ui.recordLine_tableWidget->columnCount();
- fwrite(&number, sizeof(double), 1, RecordLineFileHandle);
-
- double* data = new double[number];
- //double data[number];
- for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
- {
- for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
- {
- data[i * ui.recordLine_tableWidget->columnCount() + j] = ui.recordLine_tableWidget->item(i, j)->text().toDouble();
- }
- }
-
- fwrite(data, sizeof(double), number, RecordLineFileHandle);
-
- fclose(RecordLineFileHandle);
- delete[] data;
-
- //QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("保存成功!"));
+ PathLineManager::saveToFile(RecordLineFilePath, ui.recordLine_tableWidget);
}
void TwoMotorControl::onReadRecordLineFile_btn()
{
- //打开文件
FileOperation* fileOperation = new FileOperation();
string directory = fileOperation->getDirectoryOfExe();
-
QString RecordLineFilePath = QFileDialog::getOpenFileName(this, tr("Open RecordLine3 File"),
QString::fromStdString(directory),
tr("RecordLineFile (*.RecordLine3)"));
-
if (RecordLineFilePath.isEmpty())
{
return;
}
+
readRecordLineFile(RecordLineFilePath);
}
void TwoMotorControl::readRecordLineFile(QString RecordLineFilePath)
{
- FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb");
- double number;
-
- //读取数据
- fread(&number, sizeof(double), 1, RecordLineFileHandle);
-
- double* data = new double[number];
- for (size_t i = 0; i < number; i++)
- {
- fread(data + i, sizeof(double), 1, RecordLineFileHandle);
- //std::cout << *(data + i) << std::endl;
- }
-
- //向tableWidget添加采集线
- //(1)去掉tableWidget中所有的行
- int rowCount = ui.recordLine_tableWidget->rowCount();
- for (size_t i = 0; i < rowCount; i++)
- {
- ui.recordLine_tableWidget->removeRow(0);
- }
- //(2)添加行(采集线)
- int RecordLineCount = number / ui.recordLine_tableWidget->columnCount();
- for (size_t i = 0; i < RecordLineCount; i++)
- {
- ui.recordLine_tableWidget->insertRow(0);
-
- }
- //(3)向tableWidget填充数据
- for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
- {
- for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
- {
- QTableWidgetItem* tmp = new QTableWidgetItem(QString::number(data[i * ui.recordLine_tableWidget->columnCount() + j], 10, 5));
- tmp->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
- ui.recordLine_tableWidget->setItem(i, j, tmp);
- }
- }
-
- fclose(RecordLineFileHandle);
- delete[] data;
-
- //QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("读取成功!"));
+ PathLineManager::readFromFile(RecordLineFilePath, ui.recordLine_tableWidget);
}
diff --git a/HPPA/TwoMotorControl.h b/HPPA/TwoMotorControl.h
index af728c8..cb6167e 100644
--- a/HPPA/TwoMotorControl.h
+++ b/HPPA/TwoMotorControl.h
@@ -13,6 +13,8 @@
#include "SingleLensReflexCameraWindow.h"
#include "DepthCameraWindow.h"
+#include "PathLine.h"
+
#define PI 3.1415926
class TwoMotorControl : public QDialog, public MotorWindowBase