diff --git a/camhandler.cpp b/camhandler.cpp index 7df9828..0bfb9aa 100644 --- a/camhandler.cpp +++ b/camhandler.cpp @@ -4,11 +4,15 @@ // 构造/析构 // ---------------------------------------------------------------------------------------------------- -CamHandler::CamHandler(QObject *parent) - : QObject(parent), mDevice(nullptr), mStream(nullptr), mDeviceInfo(nullptr) +CamHandler::CamHandler(const QString &name,QObject *parent) + : QObject(parent) + , mDevice(nullptr) + , mStream(nullptr) + , mDeviceInfo(nullptr) { + camName = name; // <<< 增加 camName 的初始化 state = false; - saveFlag =false; + saveFlag = false; // 连接定时器的超时信号到采集槽 connect(&mAcquireTimer, &QTimer::timeout, this, &CamHandler::onAcquireTimerTimeout); @@ -19,16 +23,14 @@ CamHandler::CamHandler(QObject *parent) CamHandler::~CamHandler() { // 确保在销毁对象时清理资源 - if (mStream) - { + if (mStream) { stopAcquisition(); // 确保流和缓冲区已清理 mStream->Close(); PvStream::Free(mStream); mStream = nullptr; } - if (mDevice) - { + if (mDevice) { mDevice->Disconnect(); PvDevice::Free(mDevice); mDevice = nullptr; @@ -53,13 +55,13 @@ QList CamHandler::listAvailableDevices() mSystem.Find(); // 遍历发现的设备 - for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++) - { + for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++) { const PvDeviceInfo *lInfo = mSystem.GetDeviceInfo(i); // 获取设备的显示ID (例如:型号/序列号) QString lDisplayID = QString::fromLocal8Bit(lInfo->GetDisplayID().GetAscii()); - deviceList.append(lDisplayID + " (ID: " + QString::fromLocal8Bit(lInfo->GetConnectionID().GetAscii()) + ")"); + deviceList.append(lDisplayID + " (ID: " + + QString::fromLocal8Bit(lInfo->GetConnectionID().GetAscii()) + ")"); } return deviceList; @@ -68,9 +70,8 @@ QList CamHandler::listAvailableDevices() bool CamHandler::connectToDevice(const QString &aConnectionID) { QString errMsg; - if (mDevice) - { - emit logMsg( "Already connected. Please disconnect first."); + if (mDevice) { + emit logMsg("Already connected. Please disconnect first."); return false; } @@ -78,9 +79,8 @@ bool CamHandler::connectToDevice(const QString &aConnectionID) // 确保在 selectDevice 前调用 Find() (虽然 listAvailableDevices 可能已经调用,但再次调用更安全) mDeviceInfo = selectDevice(aConnectionID); - if (!mDeviceInfo) - { - errMsg = "Error: Device not found for ID:" + aConnectionID; + if (!mDeviceInfo) { + errMsg = "Error: Device not found for ID:" + aConnectionID; emit logMsg(errMsg); return false; } @@ -90,15 +90,14 @@ bool CamHandler::connectToDevice(const QString &aConnectionID) PvResult lResult; mDevice = PvDevice::CreateAndConnect(mDeviceInfo, &lResult); - if (mDevice == nullptr) - { - emit logMsg( "Error: Unable to connect to device. Result:" + QString(lResult.GetCodeString())); + if (mDevice == nullptr) { + emit logMsg("Error: Unable to connect to device. Result:" + + QString(lResult.GetCodeString())); return false; } // 3. 打开流 - if (!openStream()) - { + if (!openStream()) { disconnectDevice(); return false; } @@ -109,7 +108,7 @@ bool CamHandler::connectToDevice(const QString &aConnectionID) // 5. 创建和队列缓冲区 // createStreamBuffers(); - emit logMsg( "Successfully connected and configured stream."); + emit logMsg("Successfully connected and configured stream."); state = true; return true; } @@ -118,9 +117,8 @@ void CamHandler::startAcquisition() { // 5. 创建和队列缓冲区 createStreamBuffers(); - if (!mDevice || !mStream) - { - emit logMsg( "Not connected. Cannot start acquisition."); + if (!mDevice || !mStream) { + emit logMsg("Not connected. Cannot start acquisition."); return; } @@ -128,18 +126,15 @@ void CamHandler::startAcquisition() PvGenParameterArray *lDeviceParams = mDevice->GetParameters(); PvGenCommand *lStart = dynamic_cast(lDeviceParams->Get("AcquisitionStart")); - if (lStart != nullptr) - { - emit logMsg( "Enabling streaming and sending AcquisitionStart command."); + if (lStart != nullptr) { + emit logMsg("Enabling streaming and sending AcquisitionStart command."); mDevice->StreamEnable(); // 启用流 - lStart->Execute(); // 发送命令 + lStart->Execute(); // 发送命令 // 3. 启动定时器,驱动采集循环 mAcquireTimer.start(); - } - else - { - emit logMsg( "Error: AcquisitionStart command not found on device."); + } else { + emit logMsg("Error: AcquisitionStart command not found on device."); } } @@ -149,10 +144,9 @@ void CamHandler::stopAcquisition() return; // 1. 停止计时器 - if (mAcquireTimer.isActive()) - { + if (mAcquireTimer.isActive()) { mAcquireTimer.stop(); - emit logMsg( "Acquisition timer stopped."); + emit logMsg("Acquisition timer stopped."); } // 2. 获取 AcquisitionStop 命令 @@ -160,47 +154,43 @@ void CamHandler::stopAcquisition() PvGenCommand *lStop = dynamic_cast(lDeviceParams->Get("AcquisitionStop")); // 3. 停止采集和禁用流 - if (lStop != nullptr) - { - emit logMsg( "Sending AcquisitionStop command to the device"); + if (lStop != nullptr) { + emit logMsg("Sending AcquisitionStop command to the device"); lStop->Execute(); } - emit logMsg( "Disable streaming on the controller."); + emit logMsg("Disable streaming on the controller."); mDevice->StreamDisable(); // 4. 清理缓冲区:终止队列中的所有缓冲区并将它们移到输出队列 - emit logMsg( "Aborting buffers still in stream"); + emit logMsg("Aborting buffers still in stream"); mStream->AbortQueuedBuffers(); // 5. 从输出队列中检索剩余的缓冲区,丢弃它们 PvBuffer *lBuffer = NULL; PvResult lOperationResult; // 必须清空队列,防止下次采集时使用错误的旧缓冲区 - while (mStream->GetQueuedBufferCount() > 0) - { + while (mStream->GetQueuedBufferCount() > 0) { mStream->RetrieveBuffer(&lBuffer, &lOperationResult); // 注意:这里没有释放 lBuffer,因为缓冲区资源将在析构或断开时处理 } - emit logMsg( "Acquisition stopped and buffers cleaned up."); + emit logMsg("Acquisition stopped and buffers cleaned up."); } void CamHandler::disconnectDevice() { // 停止采集,清理流资源 - if (mStream) - { + if (mStream) { stopAcquisition(); // 确保流和缓冲区已清理 - emit logMsg( "Closing stream"); + emit logMsg("Closing stream"); mStream->Close(); PvStream::Free(mStream); mStream = nullptr; } // 断开设备连接,释放设备资源 - if (mDevice) - { - emit logMsg( "Disconnecting device"); + if (mDevice) { + emit logMsg("Disconnecting device"); mDevice->Disconnect(); PvDevice::Free(mDevice); mDevice = nullptr; @@ -209,8 +199,8 @@ void CamHandler::disconnectDevice() // mDeviceInfo 由 mSystem 管理,置空指针 mDeviceInfo = nullptr; - emit logMsg( "Disconnected and resources freed."); - state =false; + emit logMsg("Disconnected and resources freed."); + state = false; } // ---------------------------------------------------------------------------------------------------- @@ -231,38 +221,29 @@ void CamHandler::onAcquireTimerTimeout() // 尝试检索下一个缓冲区,使用较短的超时时间 (10ms) PvResult lResult = mStream->RetrieveBuffer(&lBuffer, &lOperationResult, 10); - if (lResult.IsOK()) - { - if (lOperationResult.IsOK()) - { + if (lResult.IsOK()) { + if (lOperationResult.IsOK()) { // 成功采集到有效图像 PvPayloadType lType = lBuffer->GetPayloadType(); - if (lType == PvPayloadTypeImage) - { + if (lType == PvPayloadTypeImage) { // 转换为 QImage 并发送信号 QImage image = convertPvBufferToQImage(lBuffer); - if (!image.isNull()) - { + if (!image.isNull()) { emit imageReady(image); - } - else - { + } else { emit logMsg("Image conversion failed."); } - } - else - { - emit logMsg( "Buffer retrieved, but does not contain an image payload. Requeuing."); + } else { + emit logMsg("Buffer retrieved, but does not contain an image payload. Requeuing."); } // 重新排队缓冲区 mStream->QueueBuffer(lBuffer); - } - else - { + } else { // 检索到缓冲区但操作结果不成功(例如:超时、重发过多) - emit logMsg( "RetrieveBuffer operation result is not OK:" + QString(lOperationResult.GetCodeString()) + ". Requeuing."); + emit logMsg("RetrieveBuffer operation result is not OK:" + + QString(lOperationResult.GetCodeString()) + ". Requeuing."); mStream->QueueBuffer(lBuffer); // 必须重新排队 } } @@ -278,13 +259,11 @@ const PvDeviceInfo *CamHandler::selectDevice(const QString &aConnectionID) { mSystem.Find(); // mSystem.Find() 已经在 connectToDevice 中调用 - for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++) - { + for (uint32_t i = 0; i < mSystem.GetDeviceCount(); i++) { const PvDeviceInfo *lInfo = mSystem.GetDeviceInfo(i); // 从成员变量 mSystem 获取 QString tmp = QString::fromLocal8Bit(lInfo->GetConnectionID().GetAscii()); - if (aConnectionID == tmp) - { + if (aConnectionID == tmp) { // 找到匹配的设备,返回的指针由 mSystem 管理,在 CamHandler 生命周期内有效 return lInfo; } @@ -294,30 +273,32 @@ const PvDeviceInfo *CamHandler::selectDevice(const QString &aConnectionID) bool CamHandler::openStream() { - emit logMsg( "Opening stream to device."); + emit logMsg("Opening stream to device."); PvResult lResult; // 使用静态工厂方法 PvStream::CreateAndOpen mStream = PvStream::CreateAndOpen(mDeviceInfo->GetConnectionID(), &lResult); - if (mStream == nullptr) - { - emit logMsg( "Error: Unable to stream from device. Result:" + QString(lResult.GetCodeString())); + if (mStream == nullptr) { + emit logMsg("Error: Unable to stream from device. Result:" + + QString(lResult.GetCodeString())); return false; } return true; } - void CamHandler::createStreamBuffers() { // 从设备获取 payload size (图像/数据的字节大小) uint32_t lSize = mDevice->GetPayloadSize(); // 确定要创建的缓冲区数量 - uint32_t lBufferCount = (mStream->GetQueuedBufferMaximum() < BUFFER_COUNT) ? mStream->GetQueuedBufferMaximum() : BUFFER_COUNT; + uint32_t lBufferCount = (mStream->GetQueuedBufferMaximum() < BUFFER_COUNT) + ? mStream->GetQueuedBufferMaximum() + : BUFFER_COUNT; - emit logMsg( "Allocating" + QString::number(lBufferCount) + " buffers of size " + QString::number(lSize) + " bytes."); + emit logMsg("Allocating" + QString::number(lBufferCount) + " buffers of size " + + QString::number(lSize) + " bytes."); // 分配 PvBuffer 数组 // 注意:在析构函数或 disconnectDevice 中需要释放这个内存! @@ -326,8 +307,7 @@ void CamHandler::createStreamBuffers() // **重要提示:您的原始代码没有在析构函数中释放 lBuffers 指针!** // 这是一个内存泄漏风险。要解决这个问题,您需要将 lBuffers 存储为一个成员变量 (例如 QList) // 或者只在析构函数/disconnectDevice 中确保释放它们。 - for (uint32_t i = 0; i < lBufferCount; i++) - { + for (uint32_t i = 0; i < lBufferCount; i++) { // 为每个缓冲区分配内存 (lBuffers + i)->Alloc(static_cast(lSize)); @@ -343,40 +323,30 @@ QImage CamHandler::convertPvBufferToQImage(PvBuffer *aBuffer) uint32_t lWidth = lImage->GetWidth(); uint32_t lHeight = lImage->GetHeight(); - - - // 使用全局线程池启动任务 (异步执行) // 简化实现:仅支持 Mono8 (8位灰度) 格式 - if (lImage->GetPixelType() == PvPixelMono8) - { - if(saveFlag){ + if (lImage->GetPixelType() == PvPixelMono8) { + if (saveFlag) { const void *lDataPointer = lImage->GetDataPointer(); quint32 lDataSize = lImage->GetImageSize(); // 3. 复制原始数据到 QByteArray(线程安全的关键) - QByteArray rawDataCopy( - reinterpret_cast(lDataPointer), - lDataSize - ); + QByteArray rawDataCopy(reinterpret_cast(lDataPointer), lDataSize); // 4. 创建 SaveTask 并提交给全局线程池 - SaveTask *task = new SaveTask( - rawDataCopy - ); + SaveTask *task = new SaveTask(rawDataCopy,camName); QThreadPool::globalInstance()->start(task); } // 直接使用图像数据创建 QImage - return QImage( - (uchar *)lImage->GetDataPointer(), - lWidth, - lHeight, - lWidth, // 步长/字节数 - QImage::Format_Grayscale8 - ).copy(); // .copy() 确保 QImage 拥有数据,安全地在 Qt 环境中使用 + return QImage((uchar *) lImage->GetDataPointer(), + lWidth, + lHeight, + lWidth, // 步长/字节数 + QImage::Format_Grayscale8) + .copy(); // .copy() 确保 QImage 拥有数据,安全地在 Qt 环境中使用 } - emit logMsg( "Unsupported pixel format" ); + emit logMsg("Unsupported pixel format"); return QImage(); } diff --git a/camhandler.h b/camhandler.h index 7566e4d..ae9091b 100644 --- a/camhandler.h +++ b/camhandler.h @@ -1,25 +1,25 @@ #ifndef CAMHANDLER_H #define CAMHANDLER_H +#include +#include // 用于在信号中传输图像数据 #include #include -#include -#include // 用于在信号中传输图像数据 -#include // 用于驱动采集循环 +#include // 用于驱动采集循环 // eBUS SDK 核心头文件 -#include +#include // 需要包含 QThreadPool +#include "savetask.h" +#include #include #include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include "savetask.h" -#include // 需要包含 QThreadPool +#include // 用于流缓冲区数量的定义 (参考例程) #define BUFFER_COUNT 16 @@ -29,7 +29,7 @@ class CamHandler : public QObject Q_OBJECT public: - explicit CamHandler(QObject *parent = nullptr); + explicit CamHandler(const QString &name,QObject *parent = nullptr); ~CamHandler(); // 公有接口:连接/断开/发现 @@ -43,11 +43,11 @@ public: void stopAcquisition(); bool state; bool saveFlag; - + QString camName; // ------------------- 信号 (Signals) ------------------- signals: - void imageReady(const QImage &image); // 发送采集到的图像数据 + void imageReady(const QImage &image); // 发送采集到的图像数据 void logMsg(const QString &msg); // ------------------- 槽 (Slots) ------------------- diff --git a/dialogcamset.cpp b/dialogcamset.cpp index 851df86..684bd5e 100644 --- a/dialogcamset.cpp +++ b/dialogcamset.cpp @@ -18,11 +18,9 @@ DialogCamSet::~DialogCamSet() void DialogCamSet::on_pushButton_2_clicked() { QString portName = ui->comboBox->currentText(); - if(!ph->openPort(portName)){ - QMessageBox::critical(this,"Error","Connect "+portName +" Failed"); - }else{ - QMessageBox::information(this,"Success","Connect "+portName +" Successfully"); + if (!ph->openPort(portName)) { + QMessageBox::critical(this, "Error", "Connect " + portName + " Failed"); + } else { + QMessageBox::information(this, "Success", "Connect " + portName + " Successfully"); } - } - diff --git a/dialogcamset.h b/dialogcamset.h index f6f427b..21977e7 100644 --- a/dialogcamset.h +++ b/dialogcamset.h @@ -2,8 +2,8 @@ #define DIALOGCAMSET_H #include -#include "parameterhandler.h" #include "QMessageBox" +#include "parameterhandler.h" namespace Ui { class DialogCamSet; diff --git a/mainwindow.cpp b/mainwindow.cpp index 5f634a9..6746c37 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -6,18 +6,16 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) { ui->setupUi(this); - cam1 = new CamHandler(); - cam2 = new CamHandler(); - connect(cam1,&CamHandler::logMsg,this,&MainWindow::onLogPrint1); - connect(cam1,&CamHandler::imageReady,this,&MainWindow::picUpdate1); + cam1 = new CamHandler("cam1",this); + cam2 = new CamHandler("cam2",this); + connect(cam1, &CamHandler::logMsg, this, &MainWindow::onLogPrint1); + connect(cam1, &CamHandler::imageReady, this, &MainWindow::picUpdate1); - - connect(cam2,&CamHandler::logMsg,this,&MainWindow::onLogPrint2); + connect(cam2, &CamHandler::logMsg, this, &MainWindow::onLogPrint2); m_scene1 = new QGraphicsScene(this); ui->graphicsView->setScene(m_scene1); m_imageItem1 = nullptr; // 初始化图像项指针 - } MainWindow::~MainWindow() @@ -29,23 +27,20 @@ void MainWindow::onLogPrint1(const QString &msg) { QDateTime currentDateTime = QDateTime::currentDateTime(); QString dateTimeString = currentDateTime.toString("yyyy--MM--dd HH-mm-ss"); - ui->textBrowser->append(dateTimeString+" [cam1] --> " +msg); - + ui->textBrowser->append(dateTimeString + " [cam1] --> " + msg); } void MainWindow::onLogPrint2(const QString &msg) { QDateTime currentDateTime = QDateTime::currentDateTime(); QString dateTimeString = currentDateTime.toString("yyyy--MM--dd HH-mm-ss"); - ui->textBrowser->append(dateTimeString+" [cam2] --> " +msg); - + ui->textBrowser->append(dateTimeString + " [cam2] --> " + msg); } void MainWindow::picUpdate1(const QImage &image) { // onLogPrint1("here rev"); - if (image.isNull()) - { + if (image.isNull()) { qWarning() << "Received null image."; return; } @@ -57,8 +52,7 @@ void MainWindow::picUpdate1(const QImage &image) QPixmap pixmap = QPixmap::fromImage(image); // 2. 将 QPixmap 放入 QGraphicsPixmapItem 中 - if (m_imageItem1 == nullptr) - { + if (m_imageItem1 == nullptr) { // 第一次显示图像:创建 QGraphicsPixmapItem 并添加到 Scene m_imageItem1 = m_scene1->addPixmap(pixmap); @@ -68,9 +62,7 @@ void MainWindow::picUpdate1(const QImage &image) // 可选:调整 QGraphicsView 视口以适应图像 // 如果您希望图像完整显示在 View 中,可以调用 fitInView ui->graphicsView->fitInView(m_scene1->sceneRect(), Qt::KeepAspectRatio); - } - else - { + } else { // 更新现有图像(更高效):直接更新 QGraphicsPixmapItem 的 QPixmap m_imageItem1->setPixmap(pixmap); } @@ -83,10 +75,8 @@ void MainWindow::on_pushButton_2_clicked() { dc = new DialogCamSet(this); dc->show(); - } - void MainWindow::on_pushButton_3_clicked() { @@ -97,7 +87,7 @@ void MainWindow::on_pushButton_3_clicked() // } // cam1->connectToDevice("28B702523408"); - if(!cam1->connectToDevice("28B702523408")){ + if (!cam1->connectToDevice("28B702523408")) { onLogPrint1("open failed"); return; } @@ -107,53 +97,41 @@ void MainWindow::on_pushButton_3_clicked() // return; // } - - - // cam2->startAcquisition(); } - void MainWindow::on_pushButton_4_clicked() { - if(cam1->state){ + if (cam1->state) { cam1->stopAcquisition(); - }else{ + } else { onLogPrint1("Please connect firstly"); } // cam2->stopAcquisition(); } - void MainWindow::on_pushButton_5_clicked() { ui->textBrowser->clear(); } - void MainWindow::on_pushButton_6_clicked() { - if(cam1->state){ + if (cam1->state) { cam1->startAcquisition(); - }else{ + } else { onLogPrint1("Please connect firstly"); } } - void MainWindow::on_pushButton_clicked() { - cam1->saveFlag=true; + cam1->saveFlag = true; onLogPrint1("start saving ..."); - } - void MainWindow::on_pushButton_7_clicked() { - - cam1->saveFlag=false; + cam1->saveFlag = false; onLogPrint1("stop saving ..."); - } - diff --git a/mainwindow.h b/mainwindow.h index 4c0148a..01ead37 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,13 +1,12 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include -#include "dialogcamset.h" -#include "camhandler.h" -#include "QDateTime" -#include #include - +#include +#include +#include "QDateTime" +#include "camhandler.h" +#include "dialogcamset.h" QT_BEGIN_NAMESPACE namespace Ui { @@ -28,7 +27,6 @@ public slots: void onLogPrint2(const QString &msg); void picUpdate1(const QImage &image); - private slots: void on_pushButton_2_clicked(); @@ -52,6 +50,5 @@ private: QGraphicsScene *m_scene1; QGraphicsPixmapItem *m_imageItem1; // 用于保存图像项的指针 - }; #endif // MAINWINDOW_H diff --git a/parameterhandler.cpp b/parameterhandler.cpp index 7ae9410..198521f 100644 --- a/parameterhandler.cpp +++ b/parameterhandler.cpp @@ -1,22 +1,23 @@ #include "ParameterHandler.h" -#include #include +#include #include ParameterHandler::ParameterHandler(QObject *parent) - : QObject(parent), m_serialPort(new QSerialPort(this)) + : QObject(parent) + , m_serialPort(new QSerialPort(this)) { // 将 QSerialPort 的 readyRead 信号连接到槽函数,用于数据接收 - connect(m_serialPort, &QSerialPort::readyRead, - this, &ParameterHandler::handleReadyRead); + connect(m_serialPort, &QSerialPort::readyRead, this, &ParameterHandler::handleReadyRead); // 将 QSerialPort 的 errorOccurred 信号连接到槽函数,用于错误处理 // 使用 QOverload 确保连接到正确的重载函数 - connect(m_serialPort, QOverload::of(&QSerialPort::errorOccurred), - this, &ParameterHandler::handleError); + connect(m_serialPort, + QOverload::of(&QSerialPort::errorOccurred), + this, + &ParameterHandler::handleError); } - ParameterHandler::~ParameterHandler() { // 析构时确保串口关闭 @@ -51,7 +52,8 @@ bool ParameterHandler::openPort(const QString &portName) // 1. 尝试打开串口,以读写模式 if (!m_serialPort->open(QIODevice::ReadWrite)) { - QString errorMsg = QString("无法打开串口 %1: %2").arg(portName).arg(m_serialPort->errorString()); + QString errorMsg + = QString("无法打开串口 %1: %2").arg(portName).arg(m_serialPort->errorString()); qWarning() << errorMsg; emit errorOccurred(errorMsg); return false; diff --git a/parameterhandler.h b/parameterhandler.h index d361337..32249e0 100644 --- a/parameterhandler.h +++ b/parameterhandler.h @@ -1,11 +1,11 @@ #ifndef PARAMETERHANDLER_H #define PARAMETERHANDLER_H +#include #include #include -#include -#include #include // <-- 增加此头文件 +#include class ParameterHandler : public QObject { diff --git a/savetask.cpp b/savetask.cpp index c5c7f02..4f277d1 100644 --- a/savetask.cpp +++ b/savetask.cpp @@ -1,30 +1,35 @@ +// SaveTask.cpp 文件中 + #include "SaveTask.h" -// 实际的 run() 方法在 SaveTask.cpp 中实现 void SaveTask::run() { if (m_rawData.isEmpty()) { - qWarning("SaveTask received empty raw data. Aborting save."); + qWarning("SaveTask for camera %s received empty raw data. Aborting save.", qPrintable(m_camName)); return; } - // --- 耗时的文件 I/O 操作在此处执行,不阻塞主线程 --- + // --- 耗时的文件 I/O 操作在此处执行,在线程池中 --- QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmsszzz"); - // 构造文件名:时间戳_宽度x高度_像素类型.raw - QString filename = QString("%1.raw") + // 构造文件名:相机名称_时间戳.raw + QString filename = QString("%1_%2.raw") + .arg(m_camName) .arg(timestamp); - - // 设置保存路径 - QString savePath = QDir::currentPath() + "/RawSavedImages/"; + // 使用相机名称创建保存路径的子目录 + QString savePath = QDir::currentPath() + "/RawSavedImages/" + m_camName + "/"; // <<< 增加目录 QDir dir(savePath); if (!dir.exists()) { - dir.mkpath("."); + if (!dir.mkpath(".")) + { + qWarning("Error: Failed to create save directory: %s", qPrintable(savePath)); + return; + } } QString fullPath = savePath + filename; @@ -36,16 +41,12 @@ void SaveTask::run() qint64 bytesWritten = file.write(m_rawData); file.close(); - if (bytesWritten == m_rawData.size()) - { - // 保存成功,可以发送日志或简单地使用 qInfo() - // qInfo() << "Raw data saved successfully to:" << fullPath; - } - else + if (bytesWritten != m_rawData.size()) { qWarning() << QString("Error: Only %1 of %2 bytes written to %3") .arg(bytesWritten).arg(m_rawData.size()).arg(fullPath); } + // else { qInfo() << "Raw data saved successfully to:" << fullPath; } } else { diff --git a/savetask.h b/savetask.h index 8ee8265..1bea351 100644 --- a/savetask.h +++ b/savetask.h @@ -1,12 +1,12 @@ #ifndef SAVETASK_H #define SAVETASK_H -#include #include -#include #include +#include #include #include +#include /** * @brief SaveTask 封装了将原始图像字节数据异步保存到文件的任务。 @@ -22,8 +22,8 @@ public: * @param height 图像高度。 * @param pixelType 图像的原始像素格式(例如 PvPixelMono8 的整数值)。 */ - SaveTask(const QByteArray &data) - : m_rawData(data) + SaveTask(const QByteArray &data, const QString &camName) + : m_rawData(data), m_camName(camName) // <<< 增加 camName 的初始化 { // 设置为 true,以便任务执行完成后,QThreadPool 自动清理内存 setAutoDelete(true); @@ -36,7 +36,7 @@ public: private: QByteArray m_rawData; - + QString m_camName; // <<< 增加成员变量来存储相机名称 }; #endif // SAVETASK_H