From fcc512fd6152c3daf6c4179750d52f98448ff9c6 Mon Sep 17 00:00:00 2001 From: RCi <15089880081@163.com> Date: Tue, 14 Oct 2025 20:43:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E9=9A=9C=E7=AA=97=E5=8F=A3=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=95=B0=E5=80=BC=E7=9B=91=E6=8E=A7=E3=80=82=20?= =?UTF-8?q?=E5=9C=A8=E7=AA=97=E5=8F=A3=E6=95=B0=E9=87=8F=E5=A4=A7=E4=BA=8E?= =?UTF-8?q?4=E6=97=B6=E5=90=AF=E7=94=A8=E7=AA=97=E5=8F=A3=E6=89=A9?= =?UTF-8?q?=E5=A4=A7=E6=8C=89=E9=92=AE=E3=80=82=20=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=A4=9A=E4=BD=99=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/qtBridge.h | 3 +- include/sxGlobal.h | 11 +- src/Core/back/triggerManager.cpp | 1 + src/Core/back/triggerManager.h | 21 +++ src/core/back/CLIManager.h | 4 +- src/launcher/GUI/front/pages/logPageWidget.h | 42 +----- .../GUI/uiModule/uiModule_imageView.h | 128 +++++++++++++++++- .../GUI/uiModule/uiModule_runCommand.h | 79 +++++++++-- src/launcher/main.cpp | 6 + 9 files changed, 237 insertions(+), 58 deletions(-) diff --git a/include/qtBridge.h b/include/qtBridge.h index ad20522..a75ea8f 100644 --- a/include/qtBridge.h +++ b/include/qtBridge.h @@ -66,6 +66,7 @@ signals: //排障 void runCommand_addBtn(const QString& btnName, const QString& tip, const QString& uuid); - + void runCommand_addPlcValueViewer(const QString& groupName,std::vector> viewerNameAndAddress); + void runCommand_refeshPlcValueViewer(int address,int value); }; #pragma once \ No newline at end of file diff --git a/include/sxGlobal.h b/include/sxGlobal.h index d57c51c..70613cc 100644 --- a/include/sxGlobal.h +++ b/include/sxGlobal.h @@ -120,7 +120,14 @@ public: _serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, address[i].triggerValue, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray) { evaluate(i, byteArray);}, ""); } - + for (int i = 0; i < address.size(); i++) { + _serviceManager->_triggerManager->registerPlcValueViewer(viewerNameIN + "_" + QString::number(i), + { {"触发",address[i].triggerAddr }, + {"反馈",address[i].completeAddr.toInt()}, + {"数值1",address[i].valueOffsetAddr}, + {"数值2",address[i].valueOffsetAddr + 2}, + {"数值3",address[i].valueOffsetAddr + 4} }); + } } //获取图片并进行检测 void evaluate(int batteryOffset, QByteArray& byteArray) { @@ -129,7 +136,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], ("D" + address[0].completeAddr + "_1"));//处理算法 并在取到图片后发送完成信号 diff --git a/src/Core/back/triggerManager.cpp b/src/Core/back/triggerManager.cpp index f117204..21f93fe 100644 --- a/src/Core/back/triggerManager.cpp +++ b/src/Core/back/triggerManager.cpp @@ -165,4 +165,5 @@ void triggerManager::decodeCameraCMD(readAllStruct& _struct, QByteArray byte) } checkCallback(_struct,byte); checkUnionCallback(_struct, byte); + checkPlcValueViewer(_struct, byte); } \ No newline at end of file diff --git a/src/Core/back/triggerManager.h b/src/Core/back/triggerManager.h index 556d47a..550c68b 100644 --- a/src/Core/back/triggerManager.h +++ b/src/Core/back/triggerManager.h @@ -392,6 +392,27 @@ public: return str.toStdString(); } + //SUB + void registerPlcValueViewer(const QString& groupName, const std::vector>& viewerNameAndAddress) { + for (auto& data : viewerNameAndAddress) { + if (data.second < 0)continue; + plcValueViewerDatas.push_back({ data.second, -1 }); + } + emit bridge->runCommand_addPlcValueViewer(groupName, viewerNameAndAddress); + } + void checkPlcValueViewer(readAllStruct& _struct, QByteArray& byteArray) { + QMutexLocker locer(&mutex); + for (auto& data : plcValueViewerDatas) { + int checkPos = (data.first - _struct.startPos) * 2 + 1; + if(checkPos< byteArray.size() && checkPos >= 0) + if (byteArray.at(checkPos) != data.second) { + data.second = byteArray.at(checkPos); + emit bridge->runCommand_refeshPlcValueViewer(data.first, data.second); + } + } + + } + std::vector>plcValueViewerDatas; private: QElapsedTimer lostConnectionCountTimer,lostConnectionRePrintTimer; qtFuncBridge* bridge; diff --git a/src/core/back/CLIManager.h b/src/core/back/CLIManager.h index e2db966..7d7bc5f 100644 --- a/src/core/back/CLIManager.h +++ b/src/core/back/CLIManager.h @@ -137,8 +137,10 @@ public: emit bridge->runCommand_addBtn("全部触发", tips, allTriggerUuid); QString allClearUuid = QUuid::createUuid().toString(); - emit bridge->runCommand_addBtn("全部清零", setZeroTips, allClearUuid); + emit bridge->runCommand_addBtn("触发全部清零", setZeroTips, allClearUuid); presets[allClearUuid] = setZeroCommands; + + } } diff --git a/src/launcher/GUI/front/pages/logPageWidget.h b/src/launcher/GUI/front/pages/logPageWidget.h index 302c44b..d1a7ea2 100644 --- a/src/launcher/GUI/front/pages/logPageWidget.h +++ b/src/launcher/GUI/front/pages/logPageWidget.h @@ -31,9 +31,9 @@ //行数上限 const int MAX_LOGWIDGET_LINES = 1000; //内存中存储的消息数量上限 -const int MAX_STORED_MESSAGES = 5000; +const int MAX_STORED_MESSAGES = 8000; //批量处理延迟时间(毫秒) -const int BATCH_UPDATE_DELAY = 100; +const int BATCH_UPDATE_DELAY = 300; class logWidget : public QWidget { Q_OBJECT @@ -239,7 +239,6 @@ public: [this, index]() { applyFilters(index); }); // 连接功能按钮 - connect(saveBtn, &QPushButton::clicked, [this, index]() { saveLogToFile(index); }); connect(clearBtn, &QPushButton::clicked, [this, index]() { clearLog(index); }); connect(autoScrollBtn, &QPushButton::toggled, [this, index](bool checked) { filterStates[index].autoScroll = checked; @@ -385,43 +384,6 @@ private: scrollBar->setValue(scrollBar->maximum()); } - // 保存日志到文件 - void saveLogToFile(int index) { - QMutexLocker globalLocker(&globalMutex); - - if (filterStates.find(index) == filterStates.end()) return; - - FilterState& state = filterStates[index]; - - QString fileName = QFileDialog::getSaveFileName( - this, - "保存日志文件", - QString("log_%1.txt").arg(getCurrentDate()), - "文本文件 (*.txt);;所有文件 (*.*)" - ); - - if (!fileName.isEmpty()) { - QFile file(fileName); - if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QTextStream out(&file); - out.setCodec("UTF-8"); - - // 复制当前显示的内容以避免在写入时内容发生变化 - QString content; - { - QMutexLocker stateLocker(&state.mutex); - content = state.textWidget->toPlainText(); - } - - out << content; - file.close(); - QMessageBox::information(this, "成功", "日志已保存到: " + fileName); - } else { - QMessageBox::warning(this, "错误", "无法保存文件: " + fileName); - } - } - } - // 清空日志 void clearLog(int index) { QMutexLocker globalLocker(&globalMutex); diff --git a/src/launcher/GUI/uiModule/uiModule_imageView.h b/src/launcher/GUI/uiModule/uiModule_imageView.h index 3eb94ce..79808cc 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 @@ -302,6 +302,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 +336,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 +421,16 @@ 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(); + } public slots: //combobox切换槽 void switchViewType(QString name) @@ -455,6 +499,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,19 +656,32 @@ public: ImageWidgetList.push_back(ImageView); map.insert({ windowName,ImageView }); ImageView->setTitle(windowName); - if (xPos == -1 || yPos == -1) + if (xPos == -1 || yPos == -1){ 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)); + if (ImageView->parentGridLayout->rowCount() < 3 && ImageView->parentGridLayout->columnCount() < 3) { + ImageView->zoombtn->hide(); + } return ImageView; } + 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() { diff --git a/src/launcher/GUI/uiModule/uiModule_runCommand.h b/src/launcher/GUI/uiModule/uiModule_runCommand.h index fd9d36b..41c0ea8 100644 --- a/src/launcher/GUI/uiModule/uiModule_runCommand.h +++ b/src/launcher/GUI/uiModule/uiModule_runCommand.h @@ -2,6 +2,50 @@ #include #include #include +class plcValueViewer :public QWidget{ +public: + QPalette palette; + QFont font1 = QFont("微软雅黑", 12, QFont::Bold); + QFont font2 = QFont("微软雅黑", 10, QFont::Bold); + QFont font3 = QFont("微软雅黑", 6, QFont::Bold); + plcValueViewer(const QString& groupNameIN, + const std::vector>& viewerNameAndAddress, + QMap>& plcViwerLineedits) + :groupName(groupNameIN){ + + palette.setColor(QPalette::WindowText, Qt::white); + QLabel* groupNameLabel = new QLabel(groupNameIN); + groupNameLabel->setFont(font1); + groupNameLabel->setPalette(palette); + + layout->addWidget(groupNameLabel); + for (auto& data : viewerNameAndAddress) { + plcViwerLineedits[data.second].push_back(addViewer(data.first)); + } + widget->setMaximumHeight(100); + } + QLabel* addViewer(const QString& viewerName) { + map.insert(groupName + viewerName ,new QLabel("*")); + auto label = map[groupName + viewerName]; + label->setFont(font2); + label->setPalette(palette); + + auto textLabel = new QLabel(viewerName); + textLabel->setFont(font3); + textLabel->setPalette(palette); + + QVBoxLayout* viewerLayout = new QVBoxLayout(); + viewerLayout->addWidget(label,Qt::AlignCenter); + viewerLayout->addWidget(textLabel, Qt::AlignCenter); + + layout->addLayout(viewerLayout); + return label; + } + QString groupName = ""; + QWidget* widget = new QWidget(); + QHBoxLayout* layout = new QHBoxLayout(widget); + QMap map; +}; class runCommandWidget : public QDialog { Q_OBJECT @@ -9,17 +53,20 @@ public: explicit runCommandWidget(QWidget* parent = nullptr) : QDialog(parent) { this->setWindowTitle("执行命令"); - this->resize(400, 800); - //setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); // 去掉边框 //现在、、 - //setAttribute(Qt::WA_TranslucentBackground); // 背景透明 - this->setObjectName("JsonParamTableEditor"); - this->setStyleSheet(QString("QDialog#JsonParamTableEditor {background-color: rgb(%1);border: 2px solid #000000;border-radius: 6px;}").arg(sColor_Blue)); + this->setObjectName("runCommandWidget"); + this->setStyleSheet(QString("QDialog#runCommandWidget {background-color: rgb(%1);border: 2px solid #000000;border-radius: 6px;}").arg(sColor_Blue)); btnWidgets = new QListWidget(this); btnWidgets->setStyleSheet("background: transparent;"); - QVBoxLayout* layout = new QVBoxLayout(this); - layout->addWidget(btnWidgets); - this->setFixedSize(sizeX, sizeY); + + plcValueViewerLayout = new QVBoxLayout(); + //plcValueViewerLayout->setStyleSheet("background: transparent;"); + + QGridLayout* layout = new QGridLayout(this); + layout->addWidget(btnWidgets, 0, 0); + layout->addLayout(plcValueViewerLayout, 0, 1); + + this->setFixedWidth(sizeX); } signals: @@ -28,9 +75,8 @@ signals: public slots: void addBtn(const QString& btnName, const QString& tip, const QString& uuid) { QListWidgetItem* item = new QListWidgetItem(btnWidgets); - item->setSizeHint(QSize(sizeX - 30, 30)); btnWidgets->addItem(item); - fancyButtonText* funcBtn = new fancyButtonText(btnName, sizeX - 30, 30, tip); + fancyButtonText* funcBtn = new fancyButtonText(btnName,0,0, tip); btnWidgets->setItemWidget(item, funcBtn); connect(funcBtn, &fancyButtonText::clicked, this, [this, uuid]() { QMessageBox::StandardButton reply; @@ -45,8 +91,19 @@ public slots: } }); } + void addPlcValueViewer(const QString& groupName,std::vector> viewerNameAndAddress) { + auto widget = new plcValueViewer(groupName, viewerNameAndAddress, plcViwerLineedits); + plcValueViewerLayout->addWidget(widget->widget,Qt::AlignTop); + } + void refreshPlcValueViewer(int address, int value) { + for (auto& lineedit : plcViwerLineedits[address]) { + lineedit->setText(QString::number(value)); + } + } private: - int sizeX = 300, sizeY = 500; + int sizeX = 1000, sizeY = 500; QListWidget* btnWidgets; + QVBoxLayout* plcValueViewerLayout; + QMap>plcViwerLineedits; }; #pragma once \ No newline at end of file diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index 6bb6059..15657ef 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -160,6 +160,10 @@ void connectSignalAndSlot(appCore* _core, MainWindow* _MainWindow, qtFuncBridge* QObject::connect(_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::excuteCommandPreset, [=](QString uuid) {_core->_backEnd.backend->excuteCliCommandPreset(uuid); }); + QObject::connect(bridge, &qtFuncBridge::runCommand_addPlcValueViewer, + _MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::addPlcValueViewer); + QObject::connect(bridge, &qtFuncBridge::runCommand_refeshPlcValueViewer, + _MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::refreshPlcValueViewer); } int main(int argc, char* argv[]) @@ -206,6 +210,8 @@ int main(int argc, char* argv[]) qRegisterMetaType("initStatus"); qRegisterMetaType("mat"); qRegisterMetaType>("vectorstring"); + qRegisterMetaType>>("constvpqi"); + #pragma endregion QApplication a(argc, argv); _core.initDatabase(); // 初始化数据库