增加missionSettings参数分类

增加paramEditDialog左侧窗口,根据分类显示不同参数
This commit is contained in:
2025-11-14 10:29:13 +08:00
parent 09900a1cb7
commit f9540b528c
11 changed files with 437 additions and 190 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <nlohmannJson.hpp>
#include <sql/qSqlBase.h>
@@ -78,7 +78,7 @@ public slots:
virtual void triggerAndCaptureImage(std::string cameraName, std::vector<cv::Mat>* mats) = 0;
virtual void getCameraNames(std::vector<std::string>* cameraNames) = 0;
virtual void getAllParams(std::vector<std::pair<QString, QVariant>>* params) = 0;
virtual void editParam(QString name, QVariant value) = 0;
virtual void editParam(QString group, QString name, QVariant value) = 0;
};
extern "C" {
+3 -3
View File
@@ -1,4 +1,4 @@
#include <qthread.h>
#include <qthread.h>
#include <serviceManager.h>
#include <sql/qSqlBase.h>
#include <missionLoader.h>
@@ -63,8 +63,8 @@ public:
return backendJson;
}
public slots:
void editParam(QString name, QVariant value) {
_paramSyncManager->edit(name, value);
void editParam(QString group, QString name, QVariant value) {
_paramSyncManager->edit(group, name, value);
qDebug() << name << "更改为" << value;
}
void getAllParams(std::vector<std::pair<QString, QVariant>>* params) {
+8 -8
View File
@@ -254,19 +254,19 @@ public:
imgSaveThreadManager(std::string pathIn, paramSyncManager* paramSyncManagerIn) {
_ImageSavePathFormatter.rootDir = QString::fromStdString(pathIn);
_paramSyncManager = paramSyncManagerIn;
saveOri = _paramSyncManager->get("存储原图", true).toBool();
saveRes = _paramSyncManager->get("存储结果图", true).toBool();
saveSeg = _paramSyncManager->get("存储Seg图", true).toBool();
saveCls = _paramSyncManager->get("存储Cls图", true).toBool();
saveOri = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储原图", true).toBool();
saveRes = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储结果图", true).toBool();
saveSeg = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Seg图", true).toBool();
saveCls = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Cls图", true).toBool();
}
~imgSaveThreadManager() {};
imgSaveThread saveThread;
void saveImage(std::shared_ptr <detData> data) {
if (getParamTimer.elapsed() > 5000) {
saveOri = _paramSyncManager->get("存储原图", true).toBool();
saveRes = _paramSyncManager->get("存储结果图", true).toBool();
saveSeg = _paramSyncManager->get("存储Seg图", true).toBool();
saveCls = _paramSyncManager->get("存储Cls图", true).toBool();
saveOri = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储原图", true).toBool();
saveRes = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储结果图", true).toBool();
saveSeg = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Seg图", true).toBool();
saveCls = _paramSyncManager->get(_paramSyncManager->getGroup(0), "存储Cls图", true).toBool();
getParamTimer.restart();
}
+102 -37
View File
@@ -14,48 +14,55 @@
class paramSyncManager :public QObject{
Q_OBJECT
public:
std::vector<QString> missionKey;
// 构造函数:从JSON数据初始化参数
explicit paramSyncManager(bSignalHub* _signalHub,const nlohmann::ordered_json& json = nlohmann::ordered_json::object()
):_signalHub(_signalHub){
loadFromJson(json);
}
// 获取参数值,如果不存在则返回默认值
QVariant get(QString name, QVariant defaultValue) {
//获取参数值,如果不存在则返回默认值
QVariant get(QString group, QString name, QVariant defaultValue) {
QString fullKey;
{
QMutexLocker locker(&globalMutex);
if (map.contains(name)) {
return map[name];
//构建键名(group.name)
fullKey = group + "." + name;
if (map.contains(fullKey)) {
return map[fullKey];
}
map.insert(name, defaultValue);
map.insert(fullKey, defaultValue);
}
emit _signalHub->saveMissionJson();
emit _signalHub->saveMissionJson();
return defaultValue;
}
// 编辑/设置参数值
void edit(const QString& name, const QVariant& target) {
if (map.contains(name)) {
map[name] = target;
}
else {
// 如果参数不存在,创建新的参数项
map.insert(name, target);
//编辑/设置分组参数值
void edit(const QString& group, const QString& name, const QVariant& target) {
QString fullKey = group + "." + name;
{
QMutexLocker locker(&globalMutex);
if (map.contains(fullKey)) {
map[fullKey] = target;
}
else {
map.insert(fullKey, target);
}
}
emit _signalHub->saveMissionJson();
}
// 检查参数是否存在
bool contains(const QString& name) const {
//检查参数是否存在
bool contains(const QString& fullKey) const {
QMutexLocker locker(&globalMutex);
return map.contains(name);
return map.contains(fullKey);
}
// 移除参数
bool remove(const QString& name) {
//移除参数
bool remove(const QString& fullKey) {
QMutexLocker locker(&globalMutex);
return map.remove(name) > 0;
return map.remove(fullKey) > 0;
}
// 获取所有参数名
@@ -69,35 +76,71 @@ public:
QMutexLocker locker(&globalMutex);
std::vector<std::pair<QString, QVariant>> result;
updateJsonFromMap();
for (auto it = json.begin(); it != json.end(); ++it) {
QString key = QString::fromStdString(it.key());
QVariant value = jsonToQVariant(it.value());
result.emplace_back(key, value);
}
for (auto it = map.begin(); it != map.end(); ++it) {
result.emplace_back(it.key(), it.value());
}
return result;
}
// 获取指定分组的所有参数
std::vector<std::pair<QString, QVariant>> getGroupParams(const QString& group) {
QMutexLocker locker(&globalMutex);
std::vector<std::pair<QString, QVariant>> result;
QString prefix = group + ".";
for (auto it = map.begin(); it != map.end(); ++it) {
if (it.key().startsWith(prefix)) {
QString paramName = it.key().mid(prefix.length());
result.emplace_back(paramName, it.value());
}
}
return result;
}
// 获取分组列表
std::vector<QString> getGroups() const {
QMutexLocker locker(&globalMutex);
return missionKey;
}
// 获取指定索引的分组名
QString getGroup(int index) const {
QMutexLocker locker(&globalMutex);
if (index >= 0 && index < missionKey.size()) {
return missionKey[index];
}
return QString();
}
// 从JSON加载数据
void loadFromJson(const nlohmann::ordered_json& jsonInput){
QMutexLocker locker(&globalMutex);
json = jsonInput;
map.clear();
missionKey.clear();
if (!jsonInput.is_object()) {
qDebug() << "Invalid JSON format for paramSyncManager";
return;
}
for (auto it = jsonInput.begin(); it != jsonInput.end(); ++it) {
QString key = QString::fromStdString(it.key());
QVariant value = jsonToQVariant(it.value());
map.insert(key, value);
for (auto missionIt = jsonInput.begin(); missionIt != jsonInput.end(); ++missionIt) {
QString groupName = QString::fromStdString(missionIt.key());
missionKey.push_back(groupName);
const auto& innerObject = *missionIt;
for (auto innerIt = innerObject.begin(); innerIt != innerObject.end(); ++innerIt) {
QString key = groupName + "." + QString::fromStdString(innerIt.key());
QVariant value = jsonToQVariant(innerIt.value());
map.insert(key, value);
}
}
}
// 将当前 map 值合并回初始 json 并导出
// 规则:map 中的键覆盖 json 中的同名键;json 中原有但未出现在 map 中的键保留
// 将当前 map 值合并回 json 并导出
nlohmann::ordered_json toJson() {
QMutexLocker locker(&globalMutex);
updateJsonFromMap();
@@ -105,17 +148,39 @@ public:
}
void updateJsonFromMap() {
//遍历 map,重新构建嵌套的 JSON 结构
for (auto it = map.begin(); it != map.end(); ++it) {
if (json.find(it.key().toStdString()) != json.end())
json[it.key().toStdString()] = qVariantToJson(it.value());
else
json.emplace(it.key().toStdString(), qVariantToJson(it.value()));
QString key = it.key();
//解析键名,判断是否包含分组
QStringList parts = key.split('.');
if (parts.size() == 2) {
QString group = parts[0];
QString paramName = parts.mid(1).join('.');
//确保组存在
if (json.find(group.toStdString()) == json.end()) {
json[group.toStdString()] = nlohmann::ordered_json::object();
}
//添加参数到组
json[group.toStdString()][paramName.toStdString()] = qVariantToJson(it.value());
}
else {
json[key.toStdString()] = qVariantToJson(it.value());
}
}
missionKey.clear();
for (auto it = json.begin(); it != json.end(); ++it) {
missionKey.push_back(QString::fromStdString(it.key()));
}
}
// 清空所有参数
void clear() {
QMutexLocker locker(&globalMutex);
map.clear();
json = nlohmann::ordered_json::object();
missionKey.clear();
}
private:
+297 -115
View File
@@ -23,23 +23,241 @@
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QTimer>
#include <QListWidget>
#include <QSplitter>
#include <QFrame>
class paramTableEditor : public QDialog {
Q_OBJECT
public:
explicit paramTableEditor(QWidget* parent = nullptr)
: QDialog(parent) {
this->setWindowTitle(TR("JSON Table Editor"));
this->resize(700, 450);
setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);// 去掉边框
//setAttribute(Qt::WA_TranslucentBackground); // 背景透明
this->setWindowTitle("参数编辑器");
this->resize(900, 500);
setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);
this->setObjectName("paramTableEditor");
this->setStyleSheet(QString("QDialog#paramTableEditor {background-color: rgb(%1);border: 2px solid #000000;border-radius: 6px;}").arg(sColor_Blue));
m_tableView = new QTableView(this);
m_tableModel = new QStandardItemModel(0, 2, this);// 2列:选项、值
//创建主水平布局
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
//创建侧边栏
createSidebar();
//创建分隔线
m_dividerLine = new QFrame(this);
m_dividerLine->setFrameShape(QFrame::VLine);
m_dividerLine->setFrameShadow(QFrame::Sunken);
m_dividerLine->setStyleSheet("background-color: #555555;");
m_dividerLine->setFixedWidth(1);
//创建内容区域
createContentArea();
//组装布局
mainLayout->addWidget(m_sidebarWidget);
mainLayout->addWidget(m_dividerLine);
mainLayout->addWidget(m_contentWidget, 1); //内容区域占据剩余空间
}
void setParams(std::vector<std::pair<QString, QVariant>> params) {
//保存所有参数
m_allParams = params;
//清空现有数据
m_tableModel->setRowCount(0);
m_editorWidgets.clear();
m_sidebarList->clear();
if (params.size() == 0) return;
//提取分组信息
QSet<QString> groups;
QMap<QString, std::vector<std::pair<QString, QVariant>>> groupedParams;
for (auto& data : params) {
const QString& fullKey = data.first;
QString groupName = "默认分组";
//解析分组名
int firstDotIndex = fullKey.indexOf('.');
if (firstDotIndex != -1) {
groupName = fullKey.left(firstDotIndex);
}
groups.insert(groupName);
groupedParams[groupName].push_back(data);
}
//添加分组到侧边栏
QStringList groupList = groups.values();
groupList.sort();
//添加"所有参数"选项
m_sidebarList->addItem("所有参数");
for (const QString& group : groupList) {
m_sidebarList->addItem(group);
}
//保存分组参数
m_groupedParams = groupedParams;
m_groupedParams["所有参数"] = params;// 添加所有参数选项
//默认显示所有参数
displayGroupParams("所有参数");
if (m_sidebarList->count() > 0) {
m_sidebarList->setCurrentRow(0);
}
}
private slots:
void onAccept() {
std::vector<std::pair<QString, QVariant>> result;
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 fullKey = keyItem->data(Qt::UserRole).toString();//获取完整键名
if (fullKey.isEmpty()) {
QMessageBox::warning(this, "错误", QString("第 %1 行 key 为空").arg(row + 1));
return;
}
//解析分组组名和参数名
QString group, name;
int dotIndex = fullKey.indexOf('.');
if (dotIndex != -1) {
group = fullKey.left(dotIndex);
name = fullKey.mid(dotIndex + 1);
}
else {
group = "默认分组";
name = fullKey;
}
// 获取原始类型
if (m_originalTypes.find(fullKey) == m_originalTypes.end()) {
QMessageBox::warning(this, "错误", QString("第 %1 行找不到原始类型信息").arg(row + 1));
return;
}
auto expectedType = m_originalTypes[fullKey];
// 从编辑器获取值
QVariant convertedValue;
QString errorMsg;
if (!getValueFromEditor(fullKey, expectedType, convertedValue, errorMsg)) {
QMessageBox::critical(this, "类型验证失败", QString("第 %1 行值验证失败:\n%2").arg(row + 1).arg(errorMsg));
return;
}
// 发送参数编辑信号
emit fSignalHub::getInstance()->editParam(group, name, convertedValue);
}
this->close();
delete this;
}
void onSidebarItemClicked(QListWidgetItem* item) {
if (!item) return;
QString groupName = item->text();
displayGroupParams(groupName);
}
private:
QTableView* m_tableView;
QStandardItemModel* m_tableModel;
nlohmann::json m_originalJson;
std::map<QString, QVariant::Type> m_originalTypes;
std::map<QString, QWidget*> m_editorWidgets;
//左侧边栏相关成员
QWidget* m_sidebarWidget;
QWidget* m_contentWidget;
QListWidget* m_sidebarList;
QFrame* m_dividerLine;
// 参数数据
std::vector<std::pair<QString, QVariant>> m_allParams;
QMap<QString, std::vector<std::pair<QString, QVariant>>> m_groupedParams;
void createSidebar() {
m_sidebarWidget = new QWidget(this);
m_sidebarWidget->setObjectName("sidebar");
m_sidebarWidget->setFixedWidth(180);
m_sidebarWidget->setStyleSheet(QString(R"(
QWidget#sidebar {
background-color: rgb(%1);
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
)").arg(sColor_BlueWithBlack));
QVBoxLayout* sidebarLayout = new QVBoxLayout(m_sidebarWidget);
sidebarLayout->setContentsMargins(8, 8, 8, 8);
sidebarLayout->setSpacing(10);
//左侧边栏标题
QLabel* sidebarTitle = new QLabel("参数分组");
sidebarTitle->setStyleSheet("color: white; font-weight: bold; font-size: 14px; padding: 5px;");
sidebarTitle->setAlignment(Qt::AlignCenter);
//侧边栏列表样式
m_sidebarList = new QListWidget();
m_sidebarList->setStyleSheet(R"(
QListWidget {
background-color: #3a3a3a;
border: 1px solid #555555;
border-radius: 3px;
color: white;
outline: none;
font-size: 12px;
}
QListWidget::item {
padding: 8px;
border-bottom: 1px solid #555555;
border-radius: 2px;
margin: 2px;
}
QListWidget::item:selected {
background-color: #0078d4;
color: white;
border: 1px solid #005a9e;
}
QListWidget::item:hover {
background-color: #555555;
}
)");
connect(m_sidebarList, &QListWidget::itemClicked, this, &paramTableEditor::onSidebarItemClicked);
sidebarLayout->addWidget(sidebarTitle);
sidebarLayout->addWidget(m_sidebarList);
}
void createContentArea() {
m_contentWidget = new QWidget(this);
m_contentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout* contentLayout = new QVBoxLayout(m_contentWidget);
contentLayout->setContentsMargins(10, 10, 10, 10);
contentLayout->setSpacing(10);
// 当前分组标签
m_currentGroupLabel = new QLabel("所有参数");
m_currentGroupLabel->setStyleSheet("color: white; font-weight: bold; font-size: 16px; padding: 5px;");
contentLayout->addWidget(m_currentGroupLabel);
m_tableView = new QTableView();
m_tableModel = new QStandardItemModel(0, 2, this);
m_tableView->setModel(m_tableModel);
m_tableView->setCornerButtonEnabled(false);
@@ -63,21 +281,20 @@ public:
m_tableView->setColumnWidth(0, 280);
// 禁止第一列选中
m_tableView->setColumnHidden(0, false); // 显示第一列
m_tableView->setColumnHidden(0, false);
m_tableView->setFocusPolicy(Qt::NoFocus);
//设置表头
m_tableModel->setHorizontalHeaderLabels({ TR("Option"), TR("Value") });
// 设置表头
m_tableModel->setHorizontalHeaderLabels({ "参数名", "值" });
//设置表格属性
// 设置表格属性
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
m_tableView->setAlternatingRowColors(true);
m_tableView->horizontalHeader()->setStretchLastSection(true);
m_tableView->setColumnWidth(1, 200);// 选项列宽度
m_tableView->setColumnWidth(1, 250);
fancyButtonText* okBtn = new fancyButtonText(TR("Save"), 70, 22, "");
fancyButtonText* cancelBtn = new fancyButtonText(TR("Cancel"), 70, 22, "");
fancyButtonText* okBtn = new fancyButtonText("保存", 70, 22, "");
fancyButtonText* cancelBtn = new fancyButtonText("取消", 70, 22, "");
connect(okBtn, &QPushButton::clicked, this, &paramTableEditor::onAccept);
connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
@@ -87,10 +304,9 @@ public:
btnLayout->addWidget(okBtn);
btnLayout->addWidget(cancelBtn);
QVBoxLayout* mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(m_tableView);
mainLayout->addLayout(btnLayout);
contentLayout->addWidget(m_tableView, 1); // 表格占据大部分空间
contentLayout->addLayout(btnLayout);
m_tableView->setStyleSheet(QString(R"(
QTableView {
background-color: rgb(%1);
@@ -111,7 +327,7 @@ public:
}
QTableCornerButton::section {
background: transparent;
border: none;
border: none;
}
)").arg(sColor_Blue));
@@ -135,7 +351,7 @@ border: none;
"QHeaderView {"
"background-color: rgb(%1);"
"}"
).arg(sColor_Blue));;
).arg(sColor_Blue));
m_tableView->setCornerButtonEnabled(false);
// 强制隐藏交叉方块区域
@@ -143,42 +359,59 @@ border: none;
m_tableView->horizontalHeader()->height() - 1);
m_tableView->verticalHeader()->setFixedWidth(
m_tableView->verticalHeader()->width() - 1);
}
void setParams(std::vector<std::pair<QString,QVariant>> params) {
void displayGroupParams(const QString& groupName) {
//更新当前分组标签
m_currentGroupLabel->setText(groupName);
// 清空表格
m_tableModel->setRowCount(0);
m_editorWidgets.clear();
if (params.size() == 0) return;
if (!m_groupedParams.contains(groupName)) {
return;
}
const auto& params = m_groupedParams[groupName];
int row = 0;
for (auto data : params) {
m_tableModel->insertRow(row);
const QString& key = data.first;
const QString& fullKey = data.first;
const QVariant& value = data.second;
QString displayName = fullKey;
//分组显示,去掉分组前缀
if (groupName != "所有参数") {
int dotIndex = fullKey.indexOf('.');
if (dotIndex != -1) {
displayName = fullKey.mid(dotIndex + 1);
}
}
// 设置键名(不可编辑)
QStandardItem* keyItem = new QStandardItem(key);
QStandardItem* keyItem = new QStandardItem(displayName);
keyItem->setEditable(false);
keyItem->setBackground(QColor(60, 60, 60));
keyItem->setForeground(QColor(255, 255, 255));
keyItem->setData(fullKey, Qt::UserRole);//存储完整键名
keyItem->setToolTip(fullKey);//提示显示完整键名
m_tableModel->setItem(row, 0, keyItem);
// 确定类型(内部使用,不显示)
m_originalTypes[key] = value.type();
//确定类型(内部使用,不显示)
m_originalTypes[fullKey] = value.type();
//为特定类型创建专用编辑器控件
QWidget* editorWidget = createEditorWidget(value, value.type());
if (editorWidget) {
m_tableView->setIndexWidget(m_tableModel->index(row, 1), editorWidget);
m_editorWidgets[key] = editorWidget;
m_editorWidgets[fullKey] = editorWidget;
}
else {
// 默认为文本显示
QString valueText= value.toString();
QString valueText = value.toString();
QStandardItem* valueItem = new QStandardItem(valueText);
valueItem->setToolTip(generateTypeHint(value.type()));
m_tableModel->setItem(row, 1, valueItem);
@@ -187,59 +420,10 @@ border: none;
}
}
signals:
private slots:
void onAccept() {
std::vector<std::pair<QString, QVariant>> result;
for (int row = 0; row < m_tableModel->rowCount(); ++row) {
QStandardItem* keyItem = m_tableModel->item(row, 0);
if (!keyItem) {
QMessageBox::warning(this, TR("Error"), QString(TR("Row %1 data is incomplete")).arg(row + 1));
return;
}
QString key = keyItem->text().trimmed();
if (key.isEmpty()) {
QMessageBox::warning(this, TR("Error"), QString(TR("Row %1 key is empty")).arg(row + 1));
return;
}
//获取原始类型
if (m_originalTypes.find(key) == m_originalTypes.end()) {
QMessageBox::warning(this, TR("Error"), QString(TR("Original type information not found for row %1")).arg(row + 1));
return;
}
auto expectedType = m_originalTypes[key];
//从编辑器获取值
QVariant convertedValue;
QString errorMsg;
if (!getValueFromEditor(key, expectedType, convertedValue, errorMsg)) {
QMessageBox::critical(this, TR("Type Validation Failed"),QString(TR("Row %1 value validation failed:\n%2")).arg(row + 1).arg(errorMsg));
return;
}
//esult[keyStd] = convertedValue;
//result.push_back({ key, convertedValue });
emit fSignalHub::getInstance()->editParam(key, convertedValue);
}
this->close();
delete this;
}
private:
QTableView* m_tableView;
QStandardItemModel* m_tableModel;
nlohmann::json m_originalJson; // 保存原始JSON以便类型检查
std::map<QString, QVariant::Type> m_originalTypes;// 保存每个键的原始类型
std::map<QString, QWidget*> m_editorWidgets;// 保存每个键对应的编辑器控件
// 根据类型创建不同的编辑器控件
QWidget* createEditorWidget(const QVariant& value, QVariant::Type type) {
switch (type) {
case QVariant::Type::Bool:{
case QVariant::Type::Bool: {
CircularSwitch* switchBtn = new CircularSwitch();
switchBtn->setChecked(value.toBool());
switchBtn->setToolTip(generateTypeHint(type));
@@ -248,7 +432,7 @@ private:
case QVariant::Type::Int: {
QSpinBox* spinBox = new QSpinBox();
spinBox->setMaximumWidth(160);
spinBox->setRange(INT_MIN, INT_MAX);
spinBox->setRange(-1e6, 1e6);
spinBox->setValue(value.toInt());
spinBox->setToolTip(generateTypeHint(type));
return spinBox;
@@ -257,7 +441,6 @@ private:
QDoubleSpinBox* spinBox = new QDoubleSpinBox();
spinBox->setMaximumWidth(160);
spinBox->setDecimals(3);//显示小位数
spinBox->setRange(-1e6, 1e6);
spinBox->setValue(value.toDouble());
spinBox->setToolTip(generateTypeHint(type));
return spinBox;
@@ -268,7 +451,7 @@ private:
lineEdit->setToolTip(generateTypeHint(type));
return lineEdit;
}
// 其他类型仍使用文本显示
// 其他类型仍使用文本显示
default:
return nullptr;
}
@@ -291,7 +474,7 @@ private:
updateModelData(key, value ? "true" : "false");
return true;
}
errorMsg = TR("Boolean control type mismatch");
errorMsg = "布尔值控件类型错误";
return false;
}
case QVariant::Type::Int: {
@@ -302,7 +485,7 @@ private:
updateModelData(key, QString::number(value));
return true;
}
errorMsg = TR("Integer number control type mismatch");
errorMsg = "数字控件INT类型错误";
return false;
}
case QVariant::Type::Double: {
@@ -313,7 +496,7 @@ private:
updateModelData(key, QString::number(value));
return true;
}
errorMsg = TR("Number control type mismatch");
errorMsg = "数字控件DOUBLE类型错误";
return false;
}
case QVariant::Type::String: {
@@ -324,21 +507,20 @@ private:
updateModelData(key, value);
return true;
}
errorMsg = TR("String control type mismatch");
errorMsg = "字符串控件类型错误";
return false;
}
//default:
// // 其他类型使用默认文本处理
// return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg);
}
}
//else {
// // 没有专用编辑器控件,使用默认文本处理
// return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg);
//}
else {
//没有专用编辑器控件,从单元格获取文本值
QString valueText = getTextFromCell(key);
result = valueText;
return true;
}
}
catch (const std::exception& e) {
errorMsg = QString(TR("Get value error: %1")).arg(e.what());
errorMsg = QString("获取值错误: %1").arg(e.what());
return false;
}
return false;
@@ -348,7 +530,7 @@ private:
void updateModelData(const QString& key, const QString& value) {
for (int row = 0; row < m_tableModel->rowCount(); ++row) {
QStandardItem* keyItem = m_tableModel->item(row, 0);
if (keyItem && keyItem->text() == key) {
if (keyItem && keyItem->data(Qt::UserRole).toString() == key) {
QStandardItem* valueItem = m_tableModel->item(row, 1);
if (valueItem) {
valueItem->setText(value);
@@ -359,11 +541,11 @@ private:
}
// 从单元格获取文本值(用于没有专用编辑器的类型)
QString getTextFromCell(const std::string& key) {
QString getTextFromCell(const QString& key) {
//查找键对应的行
for (int row = 0; row < m_tableModel->rowCount(); ++row) {
QStandardItem* keyItem = m_tableModel->item(row, 0);
if (keyItem && keyItem->text().toStdString() == key) {
if (keyItem && keyItem->data(Qt::UserRole).toString() == key) {
QStandardItem* valueItem = m_tableModel->item(row, 1);
if (valueItem) {
return valueItem->text();
@@ -373,23 +555,23 @@ private:
}
return "";
}
// 生成类型提示
QString generateTypeHint(QVariant::Type type) {
switch (type) {
case QVariant::Type::String:
return TR("Enter a string value (no quotes required)");
case QVariant::Type::Int:
return TR("Enter an integer value");
case QVariant::Type::Double:
return TR("Enter a decimal value");
case QVariant::Type::Bool:
return TR("Enter a boolean value (true or false)");
default:
return TR("Please enter a valid JSON value");
case QVariant::Type::String:
return "输入字符串值(不需要引号)";
case QVariant::Type::Int:
return "输入数字值(整数)";
case QVariant::Type::Double:
return "输入数字值(小数)";
case QVariant::Type::Bool:
return "输入布尔值(true 或 false)";
default:
return "请输入有效的JSON值";
}
}
};
private:
QLabel* m_currentGroupLabel; //当前分组标签
};
+1 -1
View File
@@ -57,7 +57,7 @@ signals:
void triggerAndCaptureImage(std::string cameraName, std::vector<cv::Mat>* mats);
void getCameraNames(std::vector<std::string>* cameraNames);
void getAllParams(std::vector<std::pair<QString, QVariant>>* params);
void editParam(QString name, QVariant value);
void editParam(QString group, QString name, QVariant value);
void saveMissionJson();
};
@@ -80,8 +80,8 @@ bool halconAlgo1_BaoMoHouCeMian_HouDu(std::shared_ptr <detData> data, yh_581_add
int outFlag = out_Flag.D();
TextRendererZH textPainter(Paint.cols, Paint.rows, 300);
double limitHigh = data->service->_paramSyncManager->get("最大宽度阈值(MAX)", 200).toFloat();
double limitLow = data->service->_paramSyncManager->get("最小宽度阈值(MIN)", 0).toFloat();
double limitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "最大宽度阈值(MAX)", 200).toFloat();
double limitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "最小宽度阈值(MIN)", 0).toFloat();
if (outFlag == 1) {
QMutexLocker locker(mutex);
@@ -120,10 +120,10 @@ bool halconAlgo1_BaoMoHouCeMian_PoSun(std::shared_ptr <detData> data, yh_581_add
cv::Mat img = HObject2Mat(test);
cv::resize(img, img, cv::Size(), 0.5, 0.5);
HTuple in_Parameters;
in_Parameters[0] = data->service->_paramSyncManager->get("灰度管控阈值", 230).toInt();
in_Parameters[1] = data->service->_paramSyncManager->get("缺陷像素数量管控阈值(pix)", 300000).toInt();
in_Parameters[2] = data->service->_paramSyncManager->get("缺陷的宽度管控阈值(pix)", 600).toInt();
in_Parameters[3] = data->service->_paramSyncManager->get("缺陷的高度管控阈值(pix)", 60).toInt();
in_Parameters[0] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "灰度管控阈值", 230).toInt();
in_Parameters[1] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "缺陷像素数量管控阈值(pix)", 300000).toInt();
in_Parameters[2] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "缺陷的宽度管控阈值(pix)", 600).toInt();
in_Parameters[3] = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "缺陷的高度管控阈值(pix)", 60).toInt();
HDevEngineCpp::HDevProcedure proc("_4_TR_TL_BlueCover_Inspection");
HDevProcedureCall procedureCall(proc);
@@ -173,7 +173,7 @@ bool ALGO_BaoMoHouCeMian(std::shared_ptr <detData> data, baoMoHouDaMianDetParams
clock_t start, finish;
start = clock();
data->oriImgs[0] = cv::imread("D:/04QCB82602000JFB5000019N_Camera2_0.bmp", -1);
//data->oriImgs[0] = cv::imread("D:/04QCB82602000JFB5000019N_Camera2_0.bmp", -1);
//
cv::Mat src = data->oriImgs[0];
+2 -2
View File
@@ -1,4 +1,4 @@
#include <missionBase.hpp>
#include <missionBase.hpp>
#include <yhGlobal.h>
class mfd_detParams {
public:
@@ -167,7 +167,7 @@ static bool ManHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh
static bool YuHan(std::shared_ptr <detData> data, mfd_detParams* _detParams, yh_581_address address){
try {
data->service->_missionResultHandle->toBarChart("", true, {"测试"});
data->service->_paramSyncManager->get("123", 123);
//data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "123", 123);
std::map<QString, QVariant> sqlMapData;
sqlMapData["项目"] = "预焊";
sqlMapData["相机"] = "相机" + address.triggerAddr;
@@ -1,4 +1,4 @@
#include <triggerManager.h>
#include <triggerManager.h>
#include <cameraManager.h>
#include <missionBase.hpp>
#include <summaryData.h>
@@ -297,7 +297,7 @@ public:
bool initCustom() {
#pragma region 注册触发器回调
if (_serviceManager->_paramSyncManager->get("way", "IN").toString() == "IN") {
/*if (_serviceManager->_paramSyncManager->get(_serviceManager->_paramSyncManager->getGroup(1), "way", "IN").toString() == "IN") {
_2dP_address = { 8010 ,1,{8200} ,"8011" ,"-1", - 1};
_2dN_address = { 8020 ,1,{8300} ,"8021" ,"-1", -1 };
_3d_address = { 8030 ,1,{8400} ,"8031" ,"-1", -1 };
@@ -308,7 +308,7 @@ public:
_2dN_address = { 8070 ,1,{8800} ,"8071" ,"-1", -1 };
_3d_address = { 8080 ,1,{8900} ,"8081" ,"-1", -1 };
summary_triggerPos = 8090;
}
}*/
_serviceManager->_triggerManager->registerCallback(_2dP_address.triggerAddr, 1, [this](int triggerPos, int triggerValue, QByteArray& byteArray) {Qian_2D_P(byteArray); }, "2D_1拍照触发");
_serviceManager->_triggerManager->registerCallback(_2dN_address.triggerAddr, 1, [this](int triggerPos, int triggerValue, QByteArray& byteArray) {Qian_2D_N(byteArray); }, "2D_2拍照触发");
_serviceManager->_triggerManager->registerCallback(_3d_address.triggerAddr, 1, [this](int triggerPos, int triggerValue, QByteArray& byteArray) {Qian_3D_1(byteArray); }, "3D拍照触发");
@@ -177,17 +177,17 @@ bool hanHouCeLiang(std::shared_ptr <detData> data, yuHanHanHouParams* _detParams
plcResult = "1"; silieResultText = "1"; fanzheResultText = "1";
#pragma region 判断结果以及储存结果
double hanyinChangLimitHigh = data->service->_paramSyncManager->get("焊印长(上限)", 30.5).toDouble();
double hanyinChangLimitLow = data->service->_paramSyncManager->get("焊印长(下限)", 29.5).toDouble();
bool hanyinChangEnable = data->service->_paramSyncManager->get("焊印长判定启用", false).toBool();
/*double hanyinChangLimitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印长(上限)", 30.5).toDouble();
double hanyinChangLimitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印长(下限)", 29.5).toDouble();
bool hanyinChangEnable = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印长判定启用", false).toBool();
double hanyinKuanLimitHigh = data->service->_paramSyncManager->get("焊印宽(上限)", 10.5).toDouble();
double hanyinKuanLimitLow = data->service->_paramSyncManager->get("焊印宽(下限)", 9.5).toDouble();
bool hanyinKuanEnable = data->service->_paramSyncManager->get("焊印宽判定启用", false).toBool();
double hanyinKuanLimitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印宽(上限)", 10.5).toDouble();
double hanyinKuanLimitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印宽(下限)", 9.5).toDouble();
bool hanyinKuanEnable = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "焊印宽判定启用", false).toBool();
double jierChangLimitHigh = data->service->_paramSyncManager->get("极耳长度(上限)", 10.5).toDouble();
double jierChangLimitLow = data->service->_paramSyncManager->get("极耳长度(下限)", 9.5).toDouble();
bool jierChangEnable = data->service->_paramSyncManager->get("极耳长度判定启用", false).toBool();
double jierChangLimitHigh = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "极耳长度(上限)", 10.5).toDouble();
double jierChangLimitLow = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "极耳长度(下限)", 9.5).toDouble();
bool jierChangEnable = data->service->_paramSyncManager->get(data->service->_paramSyncManager->getGroup(1), "极耳长度判定启用", false).toBool();*/
#pragma endregion
data->service->_triggerManager->writeShort("D" + address.resultAddr + "_" + plcResult);//结果反馈
@@ -1,4 +1,4 @@
#include <missionBase.hpp>
#include <missionBase.hpp>
#include <sxGlobal.h>
#pragma region 算法
#include <simpleAlgo.h>
@@ -122,7 +122,7 @@ public:
}
bool initCustom() {
#pragma region 注册触发器回调
if (_serviceManager->_paramSyncManager->get("hanhou","OUT") == "OUT") {
/*if (_serviceManager->_paramSyncManager->get(_serviceManager->_paramSyncManager->getGroup(1), "hanhou","OUT") == "OUT") {
lv_top90_1.init("Camera1", "极耳尺寸-外-铝-相机1(顶部90°)", { { 522, 1,{540},"523","530",820} }, 1, &lv_90_DetParams[0], _serviceManager, bridge, hanHouCeLiang);
lv_down90_2.init("Camera2", "极耳尺寸-外-铝-相机2(底部90°)", { { 524, 1,{540},"525","532",-1} }, 1, &lv_90_DetParams[1], _serviceManager, bridge, hanHouDown);
tong_top90_3.init("Camera3", "极耳尺寸-外-铜-相机3(顶部90°)", { { 526,1,{540},"527","534",800} }, 1, &tong_90_DetParams[0], _serviceManager, bridge, hanHouCeLiang);
@@ -143,7 +143,7 @@ public:
lv_down45_6.init("Camera6", "底部撕裂-内-铝-相机6(底部45°)", { { 644, 1,{580},"645","652",-1} }, 1, &dibu_45_lv_DetParams[0], _serviceManager, bridge, hanHouDown);
tong_top45_7.init("Camera7", "底部撕裂-内-铜-相机7(顶部45°)", { { 646, 1,{580},"647","654",-1} }, 1, &dingbu_45_tong_DetParams[0], _serviceManager, bridge, hanHouDown);
tong_down45_8.init("Camera8", "底部撕裂-内-铜-相机8(底部45°)", { { 648, 1,{580},"649","656",-1} }, 1, &dibu_45_tong_DetParams[0], _serviceManager, bridge, hanHouDown);
}
}*/
#pragma endregion
return true;
}