diff --git a/include/simpleTools/windowsCtrl.hpp b/include/simpleTools/windowsCtrl.hpp index 774fcaa..4afa251 100644 --- a/include/simpleTools/windowsCtrl.hpp +++ b/include/simpleTools/windowsCtrl.hpp @@ -6,6 +6,10 @@ #include // for strstr #include #include +#include +#include +#include +#include #pragma comment(lib, "setupapi.lib") static void DisableComPort(const char* portName) { @@ -140,4 +144,41 @@ static void restartAsAdmin() { } } } +// 解析 .lnk 文件,获取目标路径 +static QString getShortcutTarget(const QString& shortcutPath) { + HRESULT hres; + CoInitialize(NULL); + IShellLink* psl; + QString targetPath; + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); + if (SUCCEEDED(hres)) { + IPersistFile* ppf; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); + if (SUCCEEDED(hres)) { + WCHAR wsz[MAX_PATH]; + shortcutPath.toWCharArray(wsz); + wsz[shortcutPath.length()] = 0; + hres = ppf->Load(wsz, STGM_READ); + if (SUCCEEDED(hres)) { + char szTarget[MAX_PATH]; + WIN32_FIND_DATA wfd; + if (SUCCEEDED(psl->GetPath(szTarget, MAX_PATH, &wfd, SLGP_UNCPRIORITY))) { + targetPath = QString::fromLocal8Bit(szTarget); + } + } + ppf->Release(); + } + psl->Release(); + } + CoUninitialize(); + return targetPath; +} +// 获取目标文件图标 +static QIcon getFileIcon(const QString& filePath, const QSize& size) { + QFileIconProvider iconProvider; + QFileInfo fileInfo(filePath); + QIcon icon = iconProvider.icon(fileInfo); + QPixmap pixmap = icon.pixmap(size); + return QIcon(pixmap); +} #pragma once \ No newline at end of file diff --git a/include/yhGlobal.h b/include/yhGlobal.h index ae354ab..f9c6591 100644 --- a/include/yhGlobal.h +++ b/include/yhGlobal.h @@ -159,7 +159,7 @@ public: auto camera = _serviceManager->_cameraManager->getCamera(cameraName); camera->clearCache(); std::shared_ptr data = _serviceManager->_detDataManager->createDetData( - QString::number(address[batteryOffset].triggerAddr), sn, 1, camera->config.oriSaveFormat);//创建数据包 + QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包 camera->captureImage(data);//拍照 data->saveObjectName = saveObjectName; generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法 @@ -233,7 +233,7 @@ public: auto camera = _serviceManager->_cameraManager->getCamera(cameraName); camera->clearCache(); std::shared_ptr data = _serviceManager->_detDataManager->createDetData( - QString::number(address[batteryOffset].triggerAddr), sn, 1, camera->config.oriSaveFormat);//创建数据包 + QString::fromStdString(cameraName), sn, 1, camera->config.oriSaveFormat);//创建数据包 camera->captureImage(data);//拍照 data->saveObjectName = saveObjectName; generalDet->ansyncProcess(data, address[batteryOffset]);//处理算法 diff --git a/src/launcher/GUI/front/pages/displayPageWidget.h b/src/launcher/GUI/front/pages/displayPageWidget.h index 5a5e699..32487eb 100644 --- a/src/launcher/GUI/front/pages/displayPageWidget.h +++ b/src/launcher/GUI/front/pages/displayPageWidget.h @@ -74,7 +74,7 @@ public: // 通用的创建工具按钮函数实现 bool createToolButton(const QString& iconPath, const QString& text, std::function clickHandler, - const QSize& buttonSize = QSize(60, 60), const QSize& iconSize = QSize(30, 30)){ + const QSize& buttonSize = QSize(100, 60), const QSize& iconSize = QSize(30, 30)){ // 参数验证 if (iconPath.isEmpty() || text.isEmpty() || !clickHandler) { @@ -105,10 +105,75 @@ public: return false; } + btn->setIcon(icon); btn->setText(text); btn->setIconSize(iconSize); - btn->setFixedSize(buttonSize.width() + 20, buttonSize.height() + 20); // 增加高度以容纳文字 + btn->setFixedSize(buttonSize.width(), buttonSize.height()); // 增加高度以容纳文字 + btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // 文字在图标下方 + + // 设置按钮样式 + btn->setStyleSheet(R"( + QToolButton { + background-color: transparent; + border: none; + color: white; + font-family: "微软雅黑"; + font-size: 14px; + font-weight: bold; + } + QToolButton:hover { + background-color: black; + border-radius: 5px; + } + )"); + + btnLayout->addWidget(btn); + btnLayout->setAlignment(Qt::AlignCenter); + + // 连接点击事件 + if (!connect(btn, &QToolButton::clicked, clickHandler)) { + delete btn; + delete btnLayout; + return false; + } + + // 添加到按钮布局容器中 + buttonsLayout->addLayout(btnLayout); + + return true; + } + bool createToolButton(QIcon icon, const QString& text, + std::function clickHandler, + const QSize& buttonSize = QSize(100, 60), const QSize& iconSize = QSize(30, 30)) { + + // 参数验证 + if (text.isEmpty() || !clickHandler) { + return false; + } + + // 创建布局 + QVBoxLayout* btnLayout = new QVBoxLayout(); + if (!btnLayout) { + return false; + } + + btnLayout->setSpacing(0); + btnLayout->setContentsMargins(0, 0, 0, 0); + + // 使用 QToolButton 来实现图标在上文字在下的效果 + QToolButton* btn = new QToolButton(this); + if (!btn) { + delete btnLayout; + return false; + } + + // 设置图标,检查图标是否加载成功 + + btn->setIcon(icon); + btn->setText(text); + btn->setIconSize(iconSize); + btn->setFixedSize(buttonSize.width(), buttonSize.height()); // 增加高度以容纳文字 btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); // 文字在图标下方 // 设置按钮样式 @@ -364,7 +429,20 @@ public: }); } #pragma endregion - +#pragma region 读取bin目录下的tools文件夹并展示 + { + std::vector files; + fileManager::getAllFiles("./tools", files, "lnk"); + for (auto& lnkPath : files) { + std::string fileName = fileManager::getFileName(lnkPath); + auto exePath = getShortcutTarget(QString::fromLocal8Bit(lnkPath.c_str())); + auto icon = getFileIcon(exePath, QSize(30, 30)); + _toolBarWidget->createToolButton(icon, QString::fromLocal8Bit(fileName.c_str()), [exePath]() { + QProcess::startDetached(exePath); + }); + } + } +#pragma endregion vLayout->addWidget(_toolBarWidget); vLayout->addWidget(&_ImageWidgetManager); diff --git a/src/launcher/GUI/uiModule/uiModule_imageView.h b/src/launcher/GUI/uiModule/uiModule_imageView.h index 5e3943f..2db683f 100644 --- a/src/launcher/GUI/uiModule/uiModule_imageView.h +++ b/src/launcher/GUI/uiModule/uiModule_imageView.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include #include @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -302,6 +303,18 @@ class ImageWidget : public QWidget { public: QComboBox switchBox; QMutex switchViewerMutex; + + //缩放状态相关 + QPushButton* zoombtn; + bool isZoomed = false; + QSize originalSize; + QPoint originalPosition; + QGridLayout* parentGridLayout = nullptr; + int originalRow = -1; + int originalColumn = -1; + int originalRowSpan = 1; + int originalColumnSpan = 1; + ImageWidget(QWidget* parent = nullptr) : QWidget(parent) { qRegisterMetaType("cv::Mat"); QVBoxLayout* layout = new QVBoxLayout(this); @@ -324,6 +337,28 @@ public: /* auto spaceItem = new QSpacerItem(100, 1); hLayout->addSpacerItem(spaceItem);*/ + zoombtn = new QPushButton(); + zoombtn->setFixedSize(16, 16); + zoombtn + ->setStyleSheet( + R"( + QPushButton { + background-color: rgba(0, 0, 0, 0.5); + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 3px; + } + QPushButton:hover { + background-color: rgba(0, 0, 0, 0.7); + border: 1px solid rgba(255, 255, 255, 0.5); + } + )" + ); + zoombtn->setIcon(QPixmap(":icon/icon/fullscreen.png")); + zoombtn->setToolTip("放大窗口"); + hLayout->addWidget(zoombtn); + connect(zoombtn, &QPushButton::clicked, this, &ImageWidget::toggleZoom); + + label = new QLabel(u8"相机标签"); label->setAlignment(Qt::AlignLeft); label->setFont(font); @@ -387,6 +422,32 @@ public: map.insert(name, QPixmap()); switchBox.addItem(name); } + + //设置父网格布局和位置信息 + void setParentGridLayout(QGridLayout* gridLayout, int row, int column, int rowSpan, int columnSpan) { + parentGridLayout = gridLayout; + originalRow = row; + originalColumn = column; + originalRowSpan = rowSpan; + originalColumnSpan = columnSpan; + originalSize = this->size(); + + } + + void updateZoomButtonVisibility() { + if (parentGridLayout) { + int rowCount = parentGridLayout->rowCount(); + int columnCount = parentGridLayout->columnCount(); + + if (rowCount < 3 && columnCount < 3) { + zoombtn->hide(); + } + else { + zoombtn->show(); + } + } + } + public slots: //combobox切换槽 void switchViewType(QString name) @@ -455,6 +516,71 @@ public slots: viewer->setImg(px); } } + + //缩放 + void toggleZoom() { + if (!parentGridLayout) return; + + if (!isZoomed) { + zoomIn();// 放大 + } + else { + zoomOut();//缩小 + } + } + // 放大窗口 + void zoomIn() { + if (isZoomed) return; + if (!parentGridLayout) return; + + // 保存原始状态 + originalSize = this->size(); + + // 在网格布局中重新放置,占据更多空间 + parentGridLayout->removeWidget(this); + + //计算父布局的总行数和总列数 + int maxRowSpan = parentGridLayout->rowCount();// 父布局总行数 + int maxColSpan = parentGridLayout->columnCount();// 父布局总列数 + //放大后的跨度 + int zoomColSize = maxColSpan - 1; + int zoomRowSize = maxRowSpan - 1; + if (originalRow >= zoomRowSize -1 || originalColumn >= zoomColSize -1) { + int x = qMax(0, originalRow - (zoomRowSize - 1)); + int y = qMax(0, originalColumn - (zoomColSize - 1)); + parentGridLayout->addWidget(this, x, y, zoomRowSize, zoomColSize); + } + else{ + parentGridLayout->addWidget(this, originalRow, originalColumn, zoomRowSize, zoomColSize); + } + + this->raise(); + // 更新按钮状态 + isZoomed = true; + zoombtn->setIcon(QIcon(":/icon/icon/fullscreen-exit.png")); + zoombtn->setToolTip("缩小窗口"); + + // 强制更新布局 + parentGridLayout->update(); + this->update(); + } + // 缩小窗口 + void zoomOut() { + if (!isZoomed) return; + + // 恢复原始布局位置 + parentGridLayout->removeWidget(this); + parentGridLayout->addWidget(this, originalRow, originalColumn, originalRowSpan, originalColumnSpan); + + //更新按钮状态 + isZoomed = false; + zoombtn->setIcon(QIcon(":/icon/icon/fullscreen.png")); + zoombtn->setToolTip("放大窗口"); + + //强制更新布局 + parentGridLayout->update(); + this->update(); + } protected: void wheelEvent(QWheelEvent* event) override { if (event->modifiers() & Qt::ControlModifier) { @@ -547,20 +673,35 @@ public: ImageWidgetList.push_back(ImageView); map.insert({ windowName,ImageView }); ImageView->setTitle(windowName); - if (xPos <= 0 || yPos <= 0) + if (xPos < 0 || yPos < 0){ Layout->addWidget(ImageView); - else + } + else { + // 指定位置布局 Layout->addWidget(ImageView, yPos, xPos); + ImageView ->setParentGridLayout(Layout, yPos, xPos, 1, 1); + } + for (auto& viewer : viewers) ImageView->createViewer(QString::fromStdString(viewer)); - return ImageView; } + void updateAllZoomButtonsVisibility() { + for (auto* widget : ImageWidgetList) { + widget->updateZoomButtonVisibility(); + } + } + + QGridLayout* Layout = new QGridLayout(); ImageWidgetManager() { this->setLayout(Layout); Layout->setContentsMargins(0, 0, 0, 0); + // 设置布局属性,允许窗口缩放 + /*Layout->setColumnStretch(0, 1); + Layout->setColumnStretch(1, 1); + Layout->setColumnStretch(2, 1);*/ } ~ImageWidgetManager() { @@ -578,72 +719,47 @@ public: } void adjustImageWidget() { if (ImageWidgetList.isEmpty()) return; - - // 清除现有布局中的所有部件 - QLayoutItem* item; - while ((item = Layout->takeAt(0)) != nullptr) { - if (item->widget()) { - Layout->removeWidget(item->widget()); - } - delete item; + std::vector> vec(Layout->rowCount(), std::vector(Layout->columnCount(),nullptr)); + for (auto& data : map) { + vec[data.second->originalRow][data.second->originalColumn] = data.second; } + for (int row = 0; row < vec.size(); row++) { + for (int col = 0; col < vec[row].size(); col++) { + if (vec[row][col] == nullptr) { + if (col > 0) { + if (vec[row][col - 1] != nullptr) { - int total = ImageWidgetList.size(); - - // 计算最佳的网格布局行列数 - int cols = static_cast(std::ceil(std::sqrt(static_cast(total)))); - int rows = static_cast(std::ceil(static_cast(total) / cols)); - - // 创建一个二维数组来跟踪布局占用情况 - QVector> occupied(rows, QVector(cols, false)); - QVector> widgetSpans(rows, QVector(cols, QPoint(1, 1))); - - // 首先按基本网格放置部件 - int index = 0; - for (int row = 0; row < rows && index < total; ++row) { - for (int col = 0; col < cols && index < total; ++col) { - Layout->addWidget(ImageWidgetList[index], row, col); - occupied[row][col] = true; - index++; - } - } - - // 查找和填充空缺 - for (int row = 0; row < rows; ++row) { - for (int col = 0; col < cols; ++col) { - if (!occupied[row][col]) { - // 优先检查左侧部件是否可以横向扩展 - if (col > 0 && occupied[row][col-1]) { - int spanX = widgetSpans[row][col-1].x(); - int spanY = widgetSpans[row][col-1].y(); - QLayoutItem* item = Layout->itemAtPosition(row, col-1); - if (item && item->widget()) { - Layout->removeItem(item); - Layout->addWidget(item->widget(), row, col-1, spanY, spanX + 1); - widgetSpans[row][col-1].setX(spanX + 1); - occupied[row][col] = true; + vec[row][col - 1]->originalColumnSpan++; + Layout->removeWidget(vec[row][col - 1]); + Layout->addWidget(vec[row][col - 1], + vec[row][col - 1]->originalRow, + vec[row][col - 1]->originalColumn, + vec[row][col - 1]->originalRowSpan, + vec[row][col - 1]->originalColumnSpan); + vec[row][col] = vec[row][col - 1]; } } - // 如果左侧扩展不可行,尝试上方部件是否可以纵向扩展 - else if (row > 0 && occupied[row-1][col]) { - int spanX = widgetSpans[row-1][col].x(); - int spanY = widgetSpans[row-1][col].y(); - QLayoutItem* item = Layout->itemAtPosition(row-1, col); - if (item && item->widget()) { - Layout->removeItem(item); - Layout->addWidget(item->widget(), row-1, col, spanY + 1, spanX); - widgetSpans[row-1][col].setY(spanY + 1); - occupied[row][col] = true; + else if (col < vec[row].size() - 1) { + if (vec[row][col + 1] != nullptr) { + + vec[row][col + 1]->originalRow--; + vec[row][col + 1]->originalColumnSpan++; + Layout->removeWidget(vec[row][col + 1]); + Layout->addWidget(vec[row][col + 1], + vec[row][col + 1]->originalRow, + vec[row][col + 1]->originalColumn, + vec[row][col + 1]->originalRowSpan, + vec[row][col + 1]->originalColumnSpan); + vec[row][col] = vec[row][col + 1]; } } } } } - // 更新布局 Layout->update(); + updateAllZoomButtonsVisibility(); } - QGridLayout* Layout = new QGridLayout(); private: QMutex mutex; QList< ImageWidget*>ImageWidgetList; diff --git a/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp index b8479f2..e0da6a5 100644 --- a/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp +++ b/src/mission/581_YiCiZhuYe_canye/581_YiCiZhuYe_canye.cpp @@ -1,7 +1,7 @@ #include <581_YiCiZhuYe_canye.h> -void exceptionResume(std::shared_ptr data, canyeParams* _detParams, sx_581_address address) { - qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode); +void exceptionResume(std::shared_ptr data, canyeParams* _detParams, sx_581_address address,QString why = "") { + qDebug() << "[Error] " << QString::fromUtf8("检测失败!") << data->uuid << QString::fromStdString(data->SNcode)<< why; cv::Mat Paint; data->oriImgs[0].copyTo(Paint); if (Paint.channels() == 1) @@ -18,7 +18,7 @@ bool yizhuCanYe(std::shared_ptr data, canyeParams* _detParams, sx_581_a { if (!_detParams->DOGLIVE) { - exceptionResume(data, _detParams, address); + exceptionResume(data, _detParams, address,"未插加密狗"); return true; } else @@ -66,7 +66,7 @@ bool yizhuCanYe(std::shared_ptr data, canyeParams* _detParams, sx_581_a } } CATCH_EXCEPTIONS - exceptionResume(data, _detParams, address); + exceptionResume(data, _detParams, address,"检测程序异常"); return true; } diff --git a/updateLog/2025-10-15/增加了点位监控.png b/updateLog/2025-10-15/增加了点位监控.png new file mode 100644 index 0000000..69ece90 Binary files /dev/null and b/updateLog/2025-10-15/增加了点位监控.png differ diff --git a/updateLog/2025-10-15/小窗放大.png b/updateLog/2025-10-15/小窗放大.png new file mode 100644 index 0000000..adcb74c Binary files /dev/null and b/updateLog/2025-10-15/小窗放大.png differ diff --git a/updateLog/2025-10-15/放在bin目录的tools文件夹中的中的快捷方式现在会出现在顶端.png b/updateLog/2025-10-15/放在bin目录的tools文件夹中的中的快捷方式现在会出现在顶端.png new file mode 100644 index 0000000..1683d7a Binary files /dev/null and b/updateLog/2025-10-15/放在bin目录的tools文件夹中的中的快捷方式现在会出现在顶端.png differ diff --git a/updateLog/2025-10-15/自动填满窗口.png b/updateLog/2025-10-15/自动填满窗口.png new file mode 100644 index 0000000..ef6c549 Binary files /dev/null and b/updateLog/2025-10-15/自动填满窗口.png differ