优化了jsoneditdialog。
增加了对通讯检测的性能监控。
This commit is contained in:
@@ -68,5 +68,8 @@ signals:
|
||||
void runCommand_addBtn(const QString& btnName, const QString& tip, const QString& uuid);
|
||||
void runCommand_addPlcValueViewer(const QString& groupName,std::vector<std::pair<QString, int>> viewerNameAndAddress);
|
||||
void runCommand_refeshPlcValueViewer(int address,int value);
|
||||
|
||||
//性能监测
|
||||
void sendTriggerManagerLoopData(int loopCounterPerMin,int maxInterval);
|
||||
};
|
||||
#pragma once
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QObject>
|
||||
#include <opencvPaintAlgo.hpp>
|
||||
#pragma region 基础函数
|
||||
|
||||
#define CATCH_EXCEPTIONS \
|
||||
catch (HDevEngineCpp::HDevEngineException& ex) { \
|
||||
std::cout << "HDevEngineException: " << ex.Message() << std::endl; \
|
||||
|
||||
+2
-2
@@ -231,7 +231,7 @@ public:
|
||||
evaluate(i, byteArray);}, "");
|
||||
//注册清除完成信号触发器 任意触发地址归零时触发一次
|
||||
_serviceManager->_triggerManager->registerCallback(address[i].triggerAddr, 0, [this, i](int triggerPos, int triggerValue, QByteArray& byteArray) {
|
||||
_serviceManager->_triggerManager->writeShort("D" + address[0].completeAddr + "_0"); }, "D" + address[0].completeAddr.toStdString() + "清零");
|
||||
_serviceManager->_triggerManager->writeShort("D" + QByteArray::number(address[0].completeAddr.toInt() + i * 2) + "_0"); }, "D" + address[0].completeAddr.toStdString() + "清零");
|
||||
}
|
||||
for (int i = 0; i < address.size(); i++) {
|
||||
_serviceManager->_triggerManager->registerPlcValueViewer(viewerNameIN + "_" + QString::number(i),
|
||||
@@ -246,7 +246,7 @@ public:
|
||||
}
|
||||
//获取图片并进行检测
|
||||
void evaluate(int batteryOffset, QByteArray& byteArray) {
|
||||
_serviceManager->_triggerManager->writeShort("D" + address[0].completeAddr + "_1");//完成信号 固定只发在第0位
|
||||
_serviceManager->_triggerManager->writeShort("D" + QByteArray::number(address[0].completeAddr.toInt() + batteryOffset) + "_1");//完成信号 根据偏移发送
|
||||
std::string sn = _serviceManager->_triggerManager->readSnFromQByteArray(byteArray, address[batteryOffset].snAddr, false, false, -1);
|
||||
auto camera = _serviceManager->_cameraManager->getCamera(cameraName);
|
||||
camera->clearCache();
|
||||
|
||||
@@ -56,8 +56,8 @@ FILE(GLOB_RECURSE APP_UI_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.ui")
|
||||
FILE(GLOB_RECURSE APP_UI_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cc")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAEK_CURRENT_BINARY_DIR})
|
||||
set(RESOURCES_DIR ${CMAKE_SOURCE_DIR}"/resources/resources.qrc")
|
||||
set(WIN_RC_DIR ${CMAKE_SOURCE_DIR}"/resources/ff.rc")
|
||||
set(RESOURCES_DIR ${CMAKE_SOURCE_DIR}/resources/resources.qrc)
|
||||
set(WIN_RC_DIR ${CMAKE_SOURCE_DIR}/resources/ff.rc)
|
||||
# 生成动态库(DLL/.so/.dylib)
|
||||
|
||||
FILE(GLOB CORE_HEADER_FILES "${PROJECT_ROOT_PATH}/include/core/*.h")
|
||||
|
||||
@@ -33,11 +33,11 @@ void triggerManager::run(){
|
||||
if(connectHost() == false)
|
||||
return;
|
||||
QThread::msleep(1000);
|
||||
QElapsedTimer heartTimer, loopCounterCollectTimer;
|
||||
int loopCounter = 0;
|
||||
while (runFlag){
|
||||
QElapsedTimer heartTimer, loopCounterCollectTimer,loopIntervalTimer;
|
||||
int loopCounter = 0,maxIntervalLog = 0,interval = 0;
|
||||
loopIntervalTimer.start();
|
||||
while (runFlag){
|
||||
reciveCommond();
|
||||
QThread::msleep(sleepIntervalMS);
|
||||
//心跳
|
||||
if (heartTimer.elapsed()> heartBeatIntervalMS) {
|
||||
sendFinsMsg(heartBeatCmds[heartBeatCmdCnt++]);
|
||||
@@ -45,12 +45,15 @@ void triggerManager::run(){
|
||||
heartBeatCmdCnt = 0;
|
||||
heartTimer.start();
|
||||
}
|
||||
// if (loopCounterCollectTimer.elapsed() > 1000) {
|
||||
//qDebug() << "loop counter:" << loopCounter << " time:" << loopCounterCollectTimer.elapsed();
|
||||
// loopCounter = 0;
|
||||
// loopCounterCollectTimer.start();
|
||||
// }
|
||||
// loopCounter++;
|
||||
if (loopCounterCollectTimer.elapsed() > 3000) {
|
||||
emit bridge->sendTriggerManagerLoopData(loopCounter / 3, maxIntervalLog);
|
||||
maxIntervalLog = 0;
|
||||
loopCounter = 0;
|
||||
loopCounterCollectTimer.start();
|
||||
}
|
||||
loopCounter++;
|
||||
QThread::msleep(qMax(0, sleepIntervalMS - (int)loopIntervalTimer.elapsed()));
|
||||
maxIntervalLog = qMax(maxIntervalLog, (int)loopIntervalTimer.restart());
|
||||
}
|
||||
}
|
||||
bool triggerManager::connectHost(){
|
||||
|
||||
@@ -238,7 +238,7 @@ public:
|
||||
std::map<QByteArray, std::vector<unionTriggerCallbackStruct>> unionTriggerCallbackFuncs;
|
||||
//联合条件的触发器注册
|
||||
bool registerUnionCallback(std::vector<std::pair<int, int>> triggerAddressAndValue,
|
||||
conditionMode mode,
|
||||
conditionMode mode,
|
||||
uniontriggerCallback func, std::string funcName = "") {
|
||||
QMutexLocker locer(&mutex);
|
||||
if (triggerAddressAndValue.size() < 2) {
|
||||
|
||||
@@ -58,8 +58,8 @@ FILE(GLOB_RECURSE APP_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||
FILE(GLOB_RECURSE APP_UI_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.ui")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAEK_CURRENT_BINARY_DIR})
|
||||
set(RESOURCES_DIR ${CMAKE_SOURCE_DIR}"/resources/resources.qrc")
|
||||
set(WIN_RC_DIR ${CMAKE_SOURCE_DIR}"/resources/ff.rc")
|
||||
set(RESOURCES_DIR ${CMAKE_SOURCE_DIR}/resources/resources.qrc)
|
||||
set(WIN_RC_DIR ${CMAKE_SOURCE_DIR}/resources/ff.rc)
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
add_executable( ${CURRENT_FOLDER}
|
||||
${APP_HEADERPP_FILES}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTableWidget>
|
||||
@@ -17,6 +17,13 @@
|
||||
#include <nlohmannjson.hpp>
|
||||
#include <global.h>
|
||||
#include <uiModule/components/fancyButton.h>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <uiModule/components/sliderSwitch.h>
|
||||
#include <QTableView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QTimer>
|
||||
|
||||
class JsonParamTableEditor : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -35,12 +42,48 @@ public:
|
||||
: QDialog(parent) {
|
||||
this->setWindowTitle("JSON 表格编辑器");
|
||||
this->resize(700, 450);
|
||||
setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); // 去掉边框 //现在、、
|
||||
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));
|
||||
m_tableWidget = new QTableWidget(0, 2, this);
|
||||
m_tableWidget->setHorizontalHeaderLabels({ "选项", "值" });
|
||||
|
||||
m_tableView = new QTableView(this);
|
||||
m_tableModel = new QStandardItemModel(0, 2, this);// 2列:选项、值
|
||||
m_tableView->setModel(m_tableModel);
|
||||
m_tableView->setCornerButtonEnabled(false);
|
||||
|
||||
// 设置无边框
|
||||
m_tableView->setFrameShape(QFrame::NoFrame);
|
||||
m_tableView->setShowGrid(false);
|
||||
|
||||
// 禁止拖动单元格大小
|
||||
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
m_tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
|
||||
// 禁止点击表头
|
||||
m_tableView->horizontalHeader()->setSectionsClickable(false);
|
||||
m_tableView->verticalHeader()->setSectionsClickable(false);
|
||||
|
||||
// 禁止点击第一列的单元格
|
||||
m_tableView->setEditTriggers(QAbstractItemView::EditTrigger::DoubleClicked | QAbstractItemView::EditTrigger::EditKeyPressed);
|
||||
m_tableView->setItemDelegateForColumn(0, new QStyledItemDelegate(m_tableView));
|
||||
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_tableView->setColumnWidth(0, 120); // 可根据实际调整
|
||||
|
||||
// 禁止第一列选中
|
||||
m_tableView->setColumnHidden(0, false); // 显示第一列
|
||||
m_tableView->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
//设置表头
|
||||
m_tableModel->setHorizontalHeaderLabels({ "选项", "值" });
|
||||
|
||||
//设置表格属性
|
||||
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_tableView->setAlternatingRowColors(true);
|
||||
m_tableView->horizontalHeader()->setStretchLastSection(true);
|
||||
m_tableView->setColumnWidth(1, 200);// 选项列宽度
|
||||
|
||||
|
||||
fancyButtonText* okBtn = new fancyButtonText("保存", 70, 22, "");
|
||||
fancyButtonText* cancelBtn = new fancyButtonText("取消", 70, 22, "");
|
||||
@@ -54,65 +97,119 @@ public:
|
||||
btnLayout->addWidget(cancelBtn);
|
||||
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->addWidget(m_tableWidget);
|
||||
mainLayout->addWidget(m_tableView);
|
||||
mainLayout->addLayout(btnLayout);
|
||||
|
||||
// 设置表格样式和属性
|
||||
m_tableWidget->setAlternatingRowColors(true);
|
||||
m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_tableWidget->horizontalHeader()->setStretchLastSection(true);
|
||||
m_tableWidget->setColumnWidth(0, 200); // 选项列宽度
|
||||
|
||||
m_tableWidget->setStyleSheet(QString(R"(
|
||||
QTableWidget {
|
||||
background-color: rgb(%1);
|
||||
font-family: "Microsoft YaHei";
|
||||
color: #ffffff;
|
||||
gridline-color: #555555;
|
||||
}
|
||||
QHeaderView::section {
|
||||
background-color: #0078d7;
|
||||
padding: 4px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
QTableWidget::item:selected {
|
||||
background-color: #0078d7;
|
||||
}
|
||||
)").arg(sColor_Blue));
|
||||
m_tableView->setStyleSheet(QString(R"(
|
||||
QTableView {
|
||||
background-color: rgb(%1);
|
||||
font-family: "Microsoft YaHei";
|
||||
color: #ffffff;
|
||||
gridline-color: #555555;
|
||||
alternate-background-color: #3a3a3a;
|
||||
}
|
||||
QTableView::item {
|
||||
background-color: transparent;
|
||||
}
|
||||
QTableView::item:selected {
|
||||
background-color: transparent;
|
||||
}
|
||||
QTableView::item:alternate {
|
||||
background-color: transparent;
|
||||
}
|
||||
QTableCornerButton::section {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
)").arg(sColor_Blue));
|
||||
|
||||
QString headerStyle = QStringLiteral(
|
||||
"QHeaderView {"
|
||||
"background-color: transparent;"
|
||||
"border: none;"
|
||||
"}"
|
||||
"QHeaderView::section {"
|
||||
"background-color: transparent;"
|
||||
"font-family: 'Microsoft YaHei';"
|
||||
"font-weight: bold;"
|
||||
"color: #ffffff;"
|
||||
"border: none;"
|
||||
"padding: 4px;"
|
||||
"}"
|
||||
);
|
||||
m_tableView->horizontalHeader()->setStyleSheet(headerStyle);
|
||||
m_tableView->verticalHeader()->setStyleSheet((
|
||||
headerStyle +
|
||||
"QHeaderView {"
|
||||
"background-color: rgb(%1);"
|
||||
"}"
|
||||
).arg(sColor_Blue));;
|
||||
m_tableView->setCornerButtonEnabled(false);
|
||||
|
||||
// 强制隐藏交叉方块区域
|
||||
m_tableView->horizontalHeader()->setFixedHeight(
|
||||
m_tableView->horizontalHeader()->height() - 1);
|
||||
m_tableView->verticalHeader()->setFixedWidth(
|
||||
m_tableView->verticalHeader()->width() - 1);
|
||||
|
||||
}
|
||||
|
||||
void setJsonObject(const nlohmann::json& json) {
|
||||
m_tableWidget->setRowCount(0);
|
||||
m_tableModel->setRowCount(0);
|
||||
m_originalJson = json; // 保存原始JSON
|
||||
m_originalTypes.clear(); // 清空原始类型映射
|
||||
m_editorWidgets.clear();
|
||||
|
||||
if (!json.is_object()) return;
|
||||
|
||||
int row = 0;
|
||||
for (auto it = json.begin(); it != json.end(); ++it) {
|
||||
int row = m_tableWidget->rowCount();
|
||||
m_tableWidget->insertRow(row);
|
||||
m_tableModel->insertRow(row);
|
||||
|
||||
const std::string& key = it.key();
|
||||
const nlohmann::json& value = it.value();
|
||||
|
||||
|
||||
//// 设置行号(不可编辑)
|
||||
//QStandardItem* rowItem = new QStandardItem(QString::number(row + 1));
|
||||
//rowItem->setEditable(false);
|
||||
//rowItem->setBackground(QColor(60, 60, 60));
|
||||
//rowItem->setForeground(QColor(255, 255, 255));
|
||||
//m_tableModel->setItem(row, 0, rowItem);
|
||||
|
||||
// 设置键名(不可编辑)
|
||||
QTableWidgetItem* keyItem = new QTableWidgetItem(QString::fromStdString(key));
|
||||
keyItem->setFlags(keyItem->flags() & ~Qt::ItemIsEditable);
|
||||
keyItem->setBackground(QColor(80, 80, 80));
|
||||
m_tableWidget->setItem(row, 0, keyItem);
|
||||
QStandardItem* keyItem = new QStandardItem(QString::fromStdString(key));
|
||||
keyItem->setEditable(false);
|
||||
keyItem->setBackground(QColor(60, 60, 60));
|
||||
keyItem->setForeground(QColor(255, 255, 255));
|
||||
m_tableModel->setItem(row, 0, keyItem);
|
||||
|
||||
// 确定类型(内部使用,不显示)
|
||||
JsonValueType valueType = getJsonValueType(value);
|
||||
m_originalTypes[key] = valueType;
|
||||
|
||||
// 设置值(可编辑,但需要类型验证)
|
||||
QString valueText = formatValueForDisplay(value, valueType);
|
||||
QTableWidgetItem* valueItem = new QTableWidgetItem(valueText);
|
||||
valueItem->setToolTip(generateTypeHint(valueType));
|
||||
m_tableWidget->setItem(row, 1, valueItem);
|
||||
////为所有类型都创建数据项
|
||||
//QString valueText = formatValueForDisplay(value, valueType);
|
||||
//QStandardItem* valueItem = new QStandardItem(valueText);
|
||||
//valueItem->setToolTip(generateTypeHint(valueType));
|
||||
//valueItem->setBackground(QColor(60, 60, 60));
|
||||
//valueItem->setForeground(QColor(255, 255, 255));
|
||||
//m_tableModel->setItem(row, 1, valueItem);
|
||||
|
||||
//为特定类型创建专用编辑器控件
|
||||
QWidget* editorWidget = createEditorWidget(value, valueType);
|
||||
if (editorWidget) {
|
||||
m_tableView->setIndexWidget(m_tableModel->index(row, 1), editorWidget);
|
||||
m_editorWidgets[key] = editorWidget;
|
||||
}
|
||||
else {
|
||||
// 默认为文本显示
|
||||
QString valueText= formatValueForDisplay(value, valueType);
|
||||
QStandardItem* valueItem = new QStandardItem(valueText);
|
||||
valueItem->setToolTip(generateTypeHint(valueType));
|
||||
m_tableModel->setItem(row, 1, valueItem);
|
||||
}
|
||||
row++;
|
||||
}
|
||||
m_tableWidget->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
signals:
|
||||
@@ -122,24 +219,20 @@ private slots:
|
||||
void onAccept() {
|
||||
nlohmann::json result = nlohmann::json::object();
|
||||
|
||||
for (int row = 0; row < m_tableWidget->rowCount(); ++row) {
|
||||
auto* keyItem = m_tableWidget->item(row, 0);
|
||||
auto* valItem = m_tableWidget->item(row, 1);
|
||||
|
||||
if (!keyItem || !valItem) {
|
||||
for (int row = 0; row < m_tableModel->rowCount(); ++row) {
|
||||
QStandardItem* keyItem = m_tableModel->item(row, 0);
|
||||
if (!keyItem) {
|
||||
QMessageBox::warning(this, "错误", QString("第 %1 行数据不完整").arg(row + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
QString key = keyItem->text().trimmed();
|
||||
QString valStr = valItem->text().trimmed();
|
||||
|
||||
if (key.isEmpty()) {
|
||||
QMessageBox::warning(this, "错误", QString("第 %1 行 key 为空").arg(row + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取原始类型
|
||||
//获取原始类型
|
||||
std::string keyStd = key.toStdString();
|
||||
if (m_originalTypes.find(keyStd) == m_originalTypes.end()) {
|
||||
QMessageBox::warning(this, "错误", QString("第 %1 行找不到原始类型信息").arg(row + 1));
|
||||
@@ -148,26 +241,160 @@ private slots:
|
||||
|
||||
JsonValueType expectedType = m_originalTypes[keyStd];
|
||||
|
||||
// 验证并转换值
|
||||
//从编辑器获取值
|
||||
nlohmann::json convertedValue;
|
||||
QString errorMsg;
|
||||
if (!validateAndConvertValue(valStr, expectedType, convertedValue, errorMsg)) {
|
||||
QMessageBox::critical(this, "类型验证失败",
|
||||
QString("第 %1 行值验证失败:\n%2").arg(row + 1).arg(errorMsg));
|
||||
if (!getValueFromEditor(keyStd, expectedType, convertedValue, errorMsg)) {
|
||||
QMessageBox::critical(this, "类型验证失败",QString("第 %1 行值验证失败:\n%2").arg(row + 1).arg(errorMsg));
|
||||
return;
|
||||
}
|
||||
|
||||
result[keyStd] = convertedValue;
|
||||
}
|
||||
|
||||
qDebug() << "Result JSON: " << QString::fromStdString(result.dump(4));
|
||||
|
||||
emit jsonAccepted(result);
|
||||
accept();
|
||||
}
|
||||
|
||||
private:
|
||||
QTableWidget* m_tableWidget;
|
||||
QTableView* m_tableView;
|
||||
QStandardItemModel* m_tableModel;
|
||||
nlohmann::json m_originalJson; // 保存原始JSON以便类型检查
|
||||
std::map<std::string, JsonValueType> m_originalTypes; // 保存每个键的原始类型
|
||||
std::map<std::string, JsonValueType> m_originalTypes;// 保存每个键的原始类型
|
||||
std::map<std::string, QWidget*> m_editorWidgets;// 保存每个键对应的编辑器控件
|
||||
|
||||
// 根据类型创建不同的编辑器控件
|
||||
QWidget* createEditorWidget(const nlohmann::json& value, JsonValueType type) {
|
||||
switch (type) {
|
||||
case JsonValueType::Boolean: {
|
||||
CircularSwitch* switchBtn = new CircularSwitch();
|
||||
switchBtn->setChecked(value.get<bool>());
|
||||
switchBtn->setToolTip(generateTypeHint(type));
|
||||
return switchBtn;
|
||||
}
|
||||
case JsonValueType::Number: {
|
||||
QDoubleSpinBox* spinBox = new QDoubleSpinBox();
|
||||
spinBox->setRange(-1e18, 1e18);
|
||||
spinBox->setDecimals(3);//显示小位数
|
||||
|
||||
if (value.is_number_integer()) {
|
||||
spinBox->setValue(value.get<int64_t>());
|
||||
spinBox->setDecimals(0);
|
||||
}
|
||||
else {
|
||||
spinBox->setValue(value.get<double>());
|
||||
}
|
||||
|
||||
spinBox->setToolTip(generateTypeHint(type));
|
||||
return spinBox;
|
||||
}
|
||||
case JsonValueType::String: {
|
||||
QLineEdit* lineEdit = new QLineEdit();
|
||||
lineEdit->setText(QString::fromStdString(value.get<std::string>()));
|
||||
lineEdit->setToolTip(generateTypeHint(type));
|
||||
return lineEdit;
|
||||
}
|
||||
// 其他类型仍使用文本显示
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool getValueFromEditor(const std::string& key, JsonValueType expectedType, nlohmann::json& result, QString& errorMsg) {
|
||||
auto it = m_editorWidgets.find(key);
|
||||
|
||||
try {
|
||||
if (it != m_editorWidgets.end()) {
|
||||
// 有专用编辑器控件
|
||||
QWidget* widget = it->second;
|
||||
switch (expectedType) {
|
||||
case JsonValueType::Boolean: {
|
||||
CircularSwitch* switchBtn = qobject_cast<CircularSwitch*>(widget);
|
||||
if (switchBtn) {
|
||||
bool value = switchBtn->isChecked();
|
||||
result = value;
|
||||
// 更新模型数据
|
||||
updateModelData(key, value ? "true" : "false");
|
||||
return true;
|
||||
}
|
||||
errorMsg = "布尔值控件类型错误";
|
||||
return false;
|
||||
}
|
||||
case JsonValueType::Number: {
|
||||
QDoubleSpinBox* spinBox = qobject_cast<QDoubleSpinBox*>(widget);
|
||||
if (spinBox) {
|
||||
double value = spinBox->value();
|
||||
// 检查是否为整数
|
||||
if (spinBox->decimals() == 0 && value == floor(value)) {
|
||||
result = static_cast<int64_t>(value);
|
||||
updateModelData(key, QString::number(static_cast<int64_t>(value)));
|
||||
}
|
||||
else {
|
||||
result = value;
|
||||
updateModelData(key, QString::number(value));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
errorMsg = "数字控件类型错误";
|
||||
return false;
|
||||
}
|
||||
case JsonValueType::String: {
|
||||
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(widget);
|
||||
if (lineEdit) {
|
||||
QString value = lineEdit->text().trimmed();
|
||||
result = value.toStdString();
|
||||
updateModelData(key, value);
|
||||
return true;
|
||||
}
|
||||
errorMsg = "字符串控件类型错误";
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
// 其他类型使用默认文本处理
|
||||
return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 没有专用编辑器控件,使用默认文本处理
|
||||
return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
errorMsg = QString("获取值错误: %1").arg(e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新模型中的数据项
|
||||
void updateModelData(const std::string& key, const QString& value) {
|
||||
for (int row = 0; row < m_tableModel->rowCount(); ++row) {
|
||||
QStandardItem* keyItem = m_tableModel->item(row, 0);
|
||||
if (keyItem && keyItem->text().toStdString() == key) {
|
||||
QStandardItem* valueItem = m_tableModel->item(row, 1);
|
||||
if (valueItem) {
|
||||
valueItem->setText(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从单元格获取文本值(用于没有专用编辑器的类型)
|
||||
QString getTextFromCell(const std::string& key) {
|
||||
//查找键对应的行
|
||||
for (int row = 0; row < m_tableModel->rowCount(); ++row) {
|
||||
QStandardItem* keyItem = m_tableModel->item(row, 0);
|
||||
if (keyItem && keyItem->text().toStdString() == key) {
|
||||
QStandardItem* valueItem = m_tableModel->item(row, 1);
|
||||
if (valueItem) {
|
||||
return valueItem->text();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// 获取JSON值的类型
|
||||
JsonValueType getJsonValueType(const nlohmann::json& value) {
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
#ifndef CIRCULARSWITCH_H
|
||||
#define CIRCULARSWITCH_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QEasingCurve>
|
||||
#include <QTimer>
|
||||
|
||||
class CircularSwitch : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int knobPosition READ knobPosition WRITE setKnobPosition NOTIFY knobPositionChanged)
|
||||
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
|
||||
|
||||
public:
|
||||
explicit CircularSwitch(QWidget* parent = nullptr)
|
||||
: QWidget(parent)
|
||||
, m_checked(false)
|
||||
, m_knobPosition(0)
|
||||
, m_animationDuration(200)
|
||||
, m_onColor(QColor("#4CD964"))
|
||||
, m_offColor(QColor("#E5E5EA"))
|
||||
, m_knobColor(Qt::white)
|
||||
, m_borderColor(QColor("#CCCCCC"))
|
||||
, m_textColor(Qt::white)
|
||||
, m_knobDiameter(0)
|
||||
, m_padding(3)
|
||||
, m_borderWidth(1)
|
||||
, m_showText(true)
|
||||
, m_trueText("true")
|
||||
, m_falseText("false")
|
||||
{
|
||||
m_animation = new QPropertyAnimation(this, "knobPosition", this);
|
||||
m_animation->setEasingCurve(QEasingCurve::OutCubic);
|
||||
m_animation->setDuration(m_animationDuration);
|
||||
|
||||
setFixedSize(70, 34); // 稍微加宽以容纳文字
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
updateKnobGeometry();
|
||||
}
|
||||
|
||||
// 获取和设置开关状态
|
||||
bool isChecked() const { return m_checked; }
|
||||
|
||||
void setChecked(bool checked) {
|
||||
if (m_checked == checked) return;
|
||||
|
||||
m_checked = checked;
|
||||
update();
|
||||
|
||||
// 启动动画
|
||||
m_animation->stop();
|
||||
m_animation->setStartValue(m_knobPosition);
|
||||
m_animation->setEndValue(checked ? width() - m_knobDiameter - m_padding : m_padding);
|
||||
m_animation->start();
|
||||
|
||||
// 延迟发射信号,让动画先执行
|
||||
QTimer::singleShot(10, this, [this, checked]() {
|
||||
emit toggled(checked);
|
||||
});
|
||||
}
|
||||
|
||||
// 颜色设置
|
||||
QColor onColor() const { return m_onColor; }
|
||||
void setOnColor(const QColor& color) {
|
||||
m_onColor = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor offColor() const { return m_offColor; }
|
||||
void setOffColor(const QColor& color) {
|
||||
m_offColor = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor knobColor() const { return m_knobColor; }
|
||||
void setKnobColor(const QColor& color) {
|
||||
m_knobColor = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor borderColor() const { return m_borderColor; }
|
||||
void setBorderColor(const QColor& color) {
|
||||
m_borderColor = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor textColor() const { return m_textColor; }
|
||||
void setTextColor(const QColor& color) {
|
||||
m_textColor = color;
|
||||
update();
|
||||
}
|
||||
|
||||
QColor backgroundColor() const {
|
||||
return m_checked ? m_onColor : m_offColor;
|
||||
}
|
||||
|
||||
void setBackgroundColor(const QColor& color) {
|
||||
if (m_checked) {
|
||||
m_onColor = color;
|
||||
}
|
||||
else {
|
||||
m_offColor = color;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
// 动画设置
|
||||
int animationDuration() const { return m_animationDuration; }
|
||||
void setAnimationDuration(int duration) {
|
||||
m_animationDuration = duration;
|
||||
m_animation->setDuration(duration);
|
||||
}
|
||||
|
||||
// 边框设置
|
||||
int borderWidth() const { return m_borderWidth; }
|
||||
void setBorderWidth(int width) {
|
||||
m_borderWidth = width;
|
||||
update();
|
||||
}
|
||||
|
||||
// 文字设置
|
||||
bool showText() const { return m_showText; }
|
||||
void setShowText(bool show) {
|
||||
m_showText = show;
|
||||
update();
|
||||
}
|
||||
|
||||
QString trueText() const { return m_trueText; }
|
||||
void setTrueText(const QString& text) {
|
||||
m_trueText = text;
|
||||
update();
|
||||
}
|
||||
|
||||
QString falseText() const { return m_falseText; }
|
||||
void setFalseText(const QString& text) {
|
||||
m_falseText = text;
|
||||
update();
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override {
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// 绘制背景
|
||||
QRect backgroundRect = rect().adjusted(m_padding, m_padding, -m_padding, -m_padding);
|
||||
QPainterPath backgroundPath;
|
||||
backgroundPath.addRoundedRect(backgroundRect, backgroundRect.height() / 2, backgroundRect.height() / 2);
|
||||
|
||||
// 绘制边框
|
||||
if (m_borderWidth > 0) {
|
||||
painter.setPen(QPen(m_borderColor, m_borderWidth));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawPath(backgroundPath);
|
||||
}
|
||||
|
||||
// 绘制填充背景
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(m_checked ? m_onColor : m_offColor);
|
||||
painter.drawPath(backgroundPath);
|
||||
|
||||
// 绘制背景文字
|
||||
if (m_showText) {
|
||||
painter.setPen(m_textColor);
|
||||
QFont font = painter.font();
|
||||
font.setPointSize(8);
|
||||
font.setBold(true);
|
||||
painter.setFont(font);
|
||||
|
||||
// 计算文字位置
|
||||
QRect textRect = backgroundRect;
|
||||
|
||||
if (m_checked) {
|
||||
// 打开状态,文字在左侧
|
||||
textRect.setRight(width() / 2);
|
||||
painter.drawText(textRect, Qt::AlignCenter, m_trueText);
|
||||
}
|
||||
else {
|
||||
// 关闭状态,文字在右侧
|
||||
textRect.setLeft(width() / 2);
|
||||
painter.drawText(textRect, Qt::AlignCenter, m_falseText);
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制滑块
|
||||
int knobY = height() / 2;
|
||||
QRect knobRect(m_knobPosition, knobY - m_knobDiameter / 2,
|
||||
m_knobDiameter, m_knobDiameter);
|
||||
|
||||
QPainterPath knobPath;
|
||||
knobPath.addEllipse(knobRect);
|
||||
|
||||
// 滑块阴影效果
|
||||
QRadialGradient gradient(knobRect.center(), m_knobDiameter / 2);
|
||||
gradient.setColorAt(0, m_knobColor.lighter(110));
|
||||
gradient.setColorAt(1, m_knobColor);
|
||||
|
||||
painter.setPen(QPen(m_borderColor, 1));
|
||||
painter.setBrush(gradient);
|
||||
painter.drawPath(knobPath);
|
||||
|
||||
// 滑块内阴影效果
|
||||
if (m_checked) {
|
||||
QRect innerKnobRect = knobRect.adjusted(3, 3, -3, -3);
|
||||
QPainterPath innerKnobPath;
|
||||
innerKnobPath.addEllipse(innerKnobRect);
|
||||
|
||||
QRadialGradient innerGradient(innerKnobRect.center(), innerKnobRect.width() / 2);
|
||||
innerGradient.setColorAt(0, QColor(255, 255, 255, 100));
|
||||
innerGradient.setColorAt(1, QColor(255, 255, 255, 0));
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(innerGradient);
|
||||
painter.drawPath(innerKnobPath);
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressEvent(QMouseEvent* event) override {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
event->accept();
|
||||
setChecked(!m_checked);
|
||||
}
|
||||
else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void resizeEvent(QResizeEvent* event) override {
|
||||
Q_UNUSED(event)
|
||||
updateKnobGeometry();
|
||||
// 更新滑块位置
|
||||
setKnobPosition(m_checked ? width() - m_knobDiameter - m_padding : m_padding);
|
||||
}
|
||||
|
||||
private:
|
||||
int knobPosition() const { return m_knobPosition; }
|
||||
|
||||
void setKnobPosition(int position) {
|
||||
if (m_knobPosition != position) {
|
||||
m_knobPosition = position;
|
||||
update();
|
||||
emit knobPositionChanged(position);
|
||||
}
|
||||
}
|
||||
|
||||
void updateKnobGeometry() {
|
||||
m_knobDiameter = height() - 2 * m_padding - 2 * m_borderWidth;
|
||||
// 确保滑块是圆形
|
||||
if (m_knobDiameter > width() / 2 - m_padding) {
|
||||
m_knobDiameter = width() / 2 - m_padding;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_checked;
|
||||
int m_knobPosition;
|
||||
int m_animationDuration;
|
||||
|
||||
QColor m_onColor;
|
||||
QColor m_offColor;
|
||||
QColor m_knobColor;
|
||||
QColor m_borderColor;
|
||||
QColor m_textColor;
|
||||
|
||||
QPropertyAnimation* m_animation;
|
||||
|
||||
int m_knobDiameter;
|
||||
int m_padding;
|
||||
int m_borderWidth;
|
||||
|
||||
// 文字相关属性
|
||||
bool m_showText;
|
||||
QString m_trueText;
|
||||
QString m_falseText;
|
||||
|
||||
signals:
|
||||
void toggled(bool checked);
|
||||
void knobPositionChanged(int position);
|
||||
void backgroundColorChanged(const QColor& color);
|
||||
};
|
||||
|
||||
#endif // CIRCULARSWITCH_H
|
||||
@@ -55,18 +55,31 @@ public:
|
||||
this->setWindowTitle("执行命令");
|
||||
this->setObjectName("runCommandWidget");
|
||||
this->setStyleSheet(QString("QDialog#runCommandWidget {background-color: rgb(%1);border: 2px solid #000000;border-radius: 6px;}").arg(sColor_Blue));
|
||||
|
||||
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
btnWidgets = new QListWidget(this);
|
||||
btnWidgets->setStyleSheet("background: transparent;");
|
||||
|
||||
plcValueViewerLayout = new QVBoxLayout();
|
||||
//plcValueViewerLayout->setStyleSheet("background: transparent;");
|
||||
QWidget* listContainer = new QWidget(this);
|
||||
plcValueViewerLayout = new QVBoxLayout(listContainer);
|
||||
plcValueViewerLayout->setContentsMargins(0, 0, 0, 0);
|
||||
plcValueViewerLayout->setSpacing(6);
|
||||
listContainer->setLayout(plcValueViewerLayout);
|
||||
listContainer->setStyleSheet("background: transparent;");
|
||||
|
||||
QScrollArea* scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setFrameShape(QFrame::NoFrame);
|
||||
scrollArea->setWidget(listContainer);
|
||||
scrollArea->setStyleSheet("background: transparent;");
|
||||
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
layout->addWidget(btnWidgets, 0, 0);
|
||||
layout->addLayout(plcValueViewerLayout, 0, 1);
|
||||
layout->addWidget(scrollArea, 0, 1);
|
||||
|
||||
this->setFixedWidth(sizeX);
|
||||
this->setMinimumHeight(sizeY);
|
||||
//this->setMaximumHeight(sizeY);
|
||||
}
|
||||
|
||||
signals:
|
||||
@@ -101,7 +114,7 @@ public slots:
|
||||
}
|
||||
}
|
||||
private:
|
||||
int sizeX = 1000, sizeY = 500;
|
||||
int sizeX = 1000, sizeY = 800;
|
||||
QListWidget* btnWidgets;
|
||||
QVBoxLayout* plcValueViewerLayout;
|
||||
QMap<int, std::vector<QLabel*>>plcViwerLineedits;
|
||||
|
||||
@@ -60,10 +60,15 @@ public:
|
||||
runStateText->setFont(font);
|
||||
runStateText->setPalette(palette);
|
||||
|
||||
triggerState =new QLabel("");
|
||||
triggerState->setFont(font);
|
||||
triggerState->setPalette(palette);
|
||||
|
||||
runStateLayout->addWidget(runStateIconLabel);
|
||||
runStateLayout->addWidget(runStateText, 1, Qt::AlignCenter);
|
||||
|
||||
mainLayout->addLayout(runStateLayout);
|
||||
mainLayout->addWidget(triggerState, 1, Qt::AlignCenter);
|
||||
}
|
||||
|
||||
layout->addLayout(mainLayout);
|
||||
@@ -72,7 +77,7 @@ public:
|
||||
"QLineEdit { background-color: #333; color: white; border-radius: 4px; padding: 2px; } "
|
||||
"QLabel { color: white; } "
|
||||
);
|
||||
//this->setFixedHeight(150);
|
||||
this->setFixedWidth(200);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -105,16 +110,19 @@ private slots:
|
||||
|
||||
runStateText->setToolTip(tooltip);
|
||||
}
|
||||
|
||||
void onMonitorError(const QString& error) {
|
||||
runStateText->setText("监控异常");
|
||||
runStateText->setStyleSheet("QLabel { color: #999; }");
|
||||
runStateText->setToolTip(QString("监控错误: %1").arg(error));
|
||||
}
|
||||
|
||||
public slots:
|
||||
void onTriggerSateChanged(int loopCounterPerMin, int maxInterval) {
|
||||
int activeThreadCount = QThreadPool::globalInstance()->activeThreadCount();
|
||||
triggerState->setText(QString::number(loopCounterPerMin) + "L " + QString::number(maxInterval) + "ms " + QString::number(activeThreadCount) + "T");
|
||||
}
|
||||
private:
|
||||
QTimer* timer;
|
||||
QLabel* softwareRunTimeValue,* runStateText;
|
||||
QLabel* softwareRunTimeValue,* runStateText,* triggerState;
|
||||
QElapsedTimer startTimer;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,5 +31,16 @@ void appConfig::parsingSettingJson()
|
||||
}
|
||||
missionJsonPath = appWorkPath.string() + "/config/" + objectSelect + ".json";
|
||||
|
||||
//if(missionJson["backend"]["missionSettings"].at)
|
||||
if (missionJson["backend"]["missionSettings"].contains("存储原图") == false) {
|
||||
missionJson["backend"]["missionSettings"]["存储原图"] = true;
|
||||
}
|
||||
if (missionJson["backend"]["missionSettings"].contains("存储结果图") == false) {
|
||||
missionJson["backend"]["missionSettings"]["存储结果图"] = true;
|
||||
}
|
||||
if (missionJson["backend"]["missionSettings"].contains("存储Seg图") == false) {
|
||||
missionJson["backend"]["missionSettings"]["存储Seg图"] = true;
|
||||
}
|
||||
if (missionJson["backend"]["missionSettings"].contains("存储Cls图") == false) {
|
||||
missionJson["backend"]["missionSettings"]["存储Cls图"] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,10 @@ void connectSignalAndSlot(appCore* _core, MainWindow* _MainWindow, qtFuncBridge*
|
||||
_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::addPlcValueViewer);
|
||||
QObject::connect(bridge, &qtFuncBridge::runCommand_refeshPlcValueViewer,
|
||||
_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::refreshPlcValueViewer);
|
||||
|
||||
//性能监测
|
||||
QObject::connect(bridge, &qtFuncBridge::sendTriggerManagerLoopData,
|
||||
_MainWindow->_displayWidget->_softwareDataDisplay, &softwareDataDisplay::onTriggerSateChanged);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
||||
@@ -13,7 +13,20 @@ public:
|
||||
# include "HalconCpp.h"
|
||||
using namespace HDevEngineCpp;
|
||||
using namespace HalconCpp;
|
||||
|
||||
void exceptionResume(std::shared_ptr<detData> data, mfd_detParams* _detParams, yh_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)
|
||||
cvtColor(Paint, Paint, cv::COLOR_GRAY2BGR);
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 15);
|
||||
textPainter.putText(Paint, "NG", cv::Point(1000, 50), cv::Scalar(0, 255, 0));
|
||||
cv::resize(Paint, Paint, cv::Size(), 0.5, 0.5);
|
||||
data->resultImgs.push_back(Paint);
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//结果反馈
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.01");//结果反馈
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.01");//结果反馈
|
||||
}
|
||||
static bool ManHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh_581_address address){
|
||||
HObject ho_in_image;
|
||||
|
||||
@@ -202,130 +215,134 @@ static bool ManHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh
|
||||
return true;
|
||||
}
|
||||
static bool YuHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh_581_address address){
|
||||
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
|
||||
std::map<QString, QVariant> sqlMapData;
|
||||
sqlMapData["项目"] = "预焊";
|
||||
sqlMapData["相机"] = "相机" + address.triggerAddr;
|
||||
///////////////////取图//处理//////////////////
|
||||
if (data->oriImgs.size() != 1){
|
||||
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
|
||||
return false;
|
||||
}
|
||||
if (data->oriImgs[0].rows == 100) {
|
||||
cv::Mat Paint;
|
||||
data->oriImgs[0].copyTo(Paint);
|
||||
cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
qDebug() << "SN" << QString::fromStdString(data->SNcode) << "algo start";
|
||||
std::map<QString, QVariant> sqlMapData;
|
||||
sqlMapData["项目"] = "预焊";
|
||||
sqlMapData["相机"] = "相机" + address.triggerAddr;
|
||||
///////////////////取图//处理//////////////////
|
||||
if (data->oriImgs.size() != 1) {
|
||||
qCritical() << "图片数量不满足要求:" << data->oriImgs.size();
|
||||
return false;
|
||||
}
|
||||
if (data->oriImgs[0].rows == 100) {
|
||||
cv::Mat Paint;
|
||||
data->oriImgs[0].copyTo(Paint);
|
||||
cv::putText(Paint, "time out", cv::Point(0, 50), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
cv::Mat Paint;
|
||||
cv::Mat src1 = data->oriImgs[0];
|
||||
if (src1.channels() != 3)
|
||||
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
|
||||
else
|
||||
src1.copyTo(Paint);
|
||||
//处理算法
|
||||
cv::Mat Paint;
|
||||
cv::Mat src1 = data->oriImgs[0];
|
||||
if (src1.channels() != 3)
|
||||
cv::cvtColor(src1, Paint, cv::COLOR_GRAY2BGR);
|
||||
else
|
||||
src1.copyTo(Paint);
|
||||
//处理算法
|
||||
#pragma region halcon处理
|
||||
QString singal_sign = address.triggerAddr;
|
||||
std::string cameraNumberStr = "1", FixtureNumber = "1";
|
||||
if (singal_sign.contains("19600")) {
|
||||
cameraNumberStr = "1";
|
||||
FixtureNumber = "1";
|
||||
}
|
||||
else if (singal_sign.contains("19602")) {
|
||||
cameraNumberStr = "1";
|
||||
FixtureNumber = "3";
|
||||
}
|
||||
else if (singal_sign.contains("19800")) {
|
||||
cameraNumberStr = "2";
|
||||
FixtureNumber = "2";
|
||||
}
|
||||
else if (singal_sign.contains("19802")) {
|
||||
cameraNumberStr = "2";
|
||||
FixtureNumber = "4";
|
||||
}
|
||||
HDevEngineCpp::HDevProcedure proc("_9_yuhan");
|
||||
HalconCpp::HObject in_Image = MatToHObject(src1);
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
|
||||
procedureCall.SetInputCtrlParamTuple("in_ProductionType", 0);
|
||||
procedureCall.SetInputCtrlParamTuple("in_Resolution", HTuple(0.00749026));
|
||||
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
|
||||
procedureCall.SetInputCtrlParamTuple("in_FixtureNumber", HTuple(FixtureNumber.c_str()));
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/yuhan_template/"));
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/yuhan_base/"));
|
||||
procedureCall.Execute();
|
||||
// <c>*output(HTuple) : < / c>
|
||||
// <c>*out_Circle, 圆心坐标(y, x, radius) < / c >
|
||||
// <c>* out_Flag, 算法执行成功标志位, 0 : 算法执行失败 1 : 算法执行成功< / c>
|
||||
// <c>*out_OffsetX : 模组X轴的补偿量(mm) < / c >
|
||||
// <c>*out_OffsetY : 模组Y轴的补偿量(mm) < / c >
|
||||
HTuple out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");
|
||||
HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
|
||||
HTuple out_OffsetX = procedureCall.GetOutputCtrlParamTuple("out_OffsetX");
|
||||
HTuple out_OffsetY = procedureCall.GetOutputCtrlParamTuple("out_OffsetY");
|
||||
QString singal_sign = address.triggerAddr;
|
||||
std::string cameraNumberStr = "1", FixtureNumber = "1";
|
||||
if (singal_sign.contains("19600")) {
|
||||
cameraNumberStr = "1";
|
||||
FixtureNumber = "1";
|
||||
}
|
||||
else if (singal_sign.contains("19602")) {
|
||||
cameraNumberStr = "1";
|
||||
FixtureNumber = "3";
|
||||
}
|
||||
else if (singal_sign.contains("19800")) {
|
||||
cameraNumberStr = "2";
|
||||
FixtureNumber = "2";
|
||||
}
|
||||
else if (singal_sign.contains("19802")) {
|
||||
cameraNumberStr = "2";
|
||||
FixtureNumber = "4";
|
||||
}
|
||||
HDevEngineCpp::HDevProcedure proc("_9_yuhan");
|
||||
HalconCpp::HObject in_Image = MatToHObject(src1);
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);
|
||||
procedureCall.SetInputCtrlParamTuple("in_ProductionType", 0);
|
||||
procedureCall.SetInputCtrlParamTuple("in_Resolution", HTuple(0.00749026));
|
||||
procedureCall.SetInputCtrlParamTuple("in_CameraNumber", HTuple(cameraNumberStr.c_str()));
|
||||
procedureCall.SetInputCtrlParamTuple("in_FixtureNumber", HTuple(FixtureNumber.c_str()));
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath1", HTuple("./halconFiles/yuhan_template/"));
|
||||
procedureCall.SetInputCtrlParamTuple("in_FilePath2", HTuple("./halconFiles/yuhan_base/"));
|
||||
procedureCall.Execute();
|
||||
// <c>*output(HTuple) : < / c>
|
||||
// <c>*out_Circle, 圆心坐标(y, x, radius) < / c >
|
||||
// <c>* out_Flag, 算法执行成功标志位, 0 : 算法执行失败 1 : 算法执行成功< / c>
|
||||
// <c>*out_OffsetX : 模组X轴的补偿量(mm) < / c >
|
||||
// <c>*out_OffsetY : 模组Y轴的补偿量(mm) < / c >
|
||||
HTuple out_Circle = procedureCall.GetOutputCtrlParamTuple("out_Circle");
|
||||
HTuple out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");
|
||||
HTuple out_OffsetX = procedureCall.GetOutputCtrlParamTuple("out_OffsetX");
|
||||
HTuple out_OffsetY = procedureCall.GetOutputCtrlParamTuple("out_OffsetY");
|
||||
#pragma endregion
|
||||
int outFlag = out_Flag.D();
|
||||
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
|
||||
if (outFlag == 1) { //-1为失败,无结果
|
||||
double offsetX;
|
||||
double offsetY;
|
||||
offsetX = 0 - out_OffsetX.D();
|
||||
offsetY = 0 - out_OffsetY.D();
|
||||
//if (singal_sign.contains("D18800"))
|
||||
// offsetX -= 0.2;
|
||||
//else if (singal_sign.contains("D19000")) {
|
||||
// offsetX -= 0.15;
|
||||
// offsetY += 0.1;
|
||||
//}
|
||||
//else if (singal_sign.contains("D19400")) {
|
||||
// offsetY -= 0.2;
|
||||
//}
|
||||
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000){
|
||||
int outFlag = out_Flag.D();
|
||||
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera::放钉" << "_SN::" << SN << ",放钉算法结果;" << out_Flag[0].D();
|
||||
TextRendererZH textPainter(Paint.cols, Paint.rows, 150);
|
||||
if (outFlag == 1) { //-1为失败,无结果
|
||||
double offsetX;
|
||||
double offsetY;
|
||||
offsetX = 0 - out_OffsetX.D();
|
||||
offsetY = 0 - out_OffsetY.D();
|
||||
//if (singal_sign.contains("D18800"))
|
||||
// offsetX -= 0.2;
|
||||
//else if (singal_sign.contains("D19000")) {
|
||||
// offsetX -= 0.15;
|
||||
// offsetY += 0.1;
|
||||
//}
|
||||
//else if (singal_sign.contains("D19400")) {
|
||||
// offsetY -= 0.2;
|
||||
//}
|
||||
if (abs(offsetX) >= 6000 || abs(offsetY) >= 6000) {
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 预焊X偏移abs(resultData[0]) >= 6000,may err,set 0";
|
||||
data->halconOK = false;
|
||||
}
|
||||
else {
|
||||
sqlMapData["偏移X"] = offsetX;
|
||||
sqlMapData["偏移Y"] = offsetY;
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(offsetX));//发送偏移X
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(offsetY));//发送偏移Y
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
|
||||
data->halconOK = true;
|
||||
}
|
||||
//圆及十字
|
||||
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
|
||||
cv::line(Paint, cv::Point(out_Circle[1].D() - 300, out_Circle[0].D()), cv::Point(out_Circle[1].D() + 300, out_Circle[0].D()), cv::Scalar(0, 255, 0), 15);
|
||||
cv::line(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D() - 300), cv::Point(out_Circle[1].D(), out_Circle[0].D() + 300), cv::Scalar(0, 255, 0), 15);
|
||||
|
||||
textPainter.putText(Paint, "X偏移:" + std::to_string(offsetX), cv::Point(50, 150), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "Y偏移:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "相机:" + cameraNumberStr + " 孔位" + FixtureNumber, cv::Point(50, 0), cv::Scalar(0, 255, 0));
|
||||
}
|
||||
else {
|
||||
data->halconOK = false;
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " 预焊X偏移abs(resultData[0]) >= 6000,may err,set 0";
|
||||
data->halconOK = false;
|
||||
textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255));
|
||||
}
|
||||
|
||||
if (data->halconOK == true) {
|
||||
textPainter.putText(Paint, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0));
|
||||
sqlMapData["结果"] = "OK";
|
||||
}
|
||||
else {
|
||||
sqlMapData["偏移X"] = offsetX;
|
||||
sqlMapData["偏移Y"] = offsetY;
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_" + QByteArray::number(offsetX));//发送偏移X
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_" + QByteArray::number(offsetY));//发送偏移Y
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_1");//发送结果
|
||||
data->halconOK = true;
|
||||
textPainter.putText(Paint, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255));
|
||||
sqlMapData["结果"] = "NG";
|
||||
}
|
||||
//圆及十字
|
||||
cv::circle(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D()), out_Circle[2].D(), cv::Scalar(0, 255, 0), 20);
|
||||
cv::line(Paint, cv::Point(out_Circle[1].D() - 300, out_Circle[0].D()), cv::Point(out_Circle[1].D() + 300, out_Circle[0].D()), cv::Scalar(0, 255, 0), 15);
|
||||
cv::line(Paint, cv::Point(out_Circle[1].D(), out_Circle[0].D() - 300), cv::Point(out_Circle[1].D(), out_Circle[0].D() + 300), cv::Scalar(0, 255, 0), 15);
|
||||
data->service->_csvWriter->addData(QString::fromStdString(data->SNcode), sqlMapData);
|
||||
data->resultImgs.push_back(Paint);
|
||||
|
||||
textPainter.putText(Paint, "X偏移:" + std::to_string(offsetX), cv::Point(50, 150), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "Y偏移:" + std::to_string(offsetY), cv::Point(50, 350), cv::Scalar(0, 255, 0));
|
||||
textPainter.putText(Paint, "相机:" + cameraNumberStr + " 孔位" + FixtureNumber, cv::Point(50, 0), cv::Scalar(0, 255, 0));
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
data->halconOK = false;
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr) + "_0.0123");//发送偏移X
|
||||
data->service->_triggerManager->writeFloat("D" + QByteArray::number(address.valueOffsetAddr + 2) + "_0.0123");//发送偏移Y
|
||||
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_2");//发送结果
|
||||
textPainter.putText(Paint, "算法异常", cv::Point(50, 300), cv::Scalar(0, 0, 255));
|
||||
}
|
||||
|
||||
if (data->halconOK == true){
|
||||
textPainter.putText(Paint, "OK", cv::Point(50, 550), cv::Scalar(0, 255, 0));
|
||||
sqlMapData["结果"] = "OK";
|
||||
}
|
||||
else{
|
||||
textPainter.putText(Paint, "NG", cv::Point(50, 500), cv::Scalar(0, 0, 255));
|
||||
sqlMapData["结果"] = "NG";
|
||||
}
|
||||
data->service->_csvWriter->addData(QString::fromStdString(data->SNcode), sqlMapData);
|
||||
data->resultImgs.push_back(Paint);
|
||||
|
||||
return true;
|
||||
CATCH_EXCEPTIONS
|
||||
exceptionResume(data, _detParams, address, "NG");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
Reference in New Issue
Block a user