From 21d8ef8c34939c50ea2eda454bb163944d7777ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=85=E9=B8=A2?= <523762293@qq.com> Date: Thu, 16 Oct 2025 15:58:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86json=20editdialog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeUserPresets.json | 24 +- src/launcher/GUI/JsonEditorDialog.h | 230 +++++++++++--- .../GUI/front/pages/displayPageWidget.h | 2 +- .../GUI/uiModule/components/sliderSwitch.h | 287 ++++++++++++++++++ 4 files changed, 496 insertions(+), 47 deletions(-) create mode 100644 src/launcher/GUI/uiModule/components/sliderSwitch.h diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json index 99cd14f..4fb04d6 100644 --- a/CMakeUserPresets.json +++ b/CMakeUserPresets.json @@ -24,17 +24,35 @@ { "hidden": true, "name": "Qt-Default", - "inherits": null, + "inherits": "allenv_qt5", "vendor": { "qt-project.org/Default": { - "checksum": "VoalogTkyWuFomeO1TLFx0olLJ4=" + "checksum": "Z8G/I2NiO/EJ3GcqVEvZ0lSrMzM=" + } + } + }, + { + "hidden": true, + "name": "allenv_qt5", + "inherits": "Qt", + "environment": { + "QTDIR": "G:/detSystem/allenv/qt5" + }, + "architecture": { + "strategy": "external", + "value": "x64" + }, + "generator": "Ninja", + "vendor": { + "qt-project.org/Version": { + "checksum": "fGB5SKr330WkMcI+0sxuX59JXuA=" } } } ], "vendor": { "qt-project.org/Presets": { - "checksum": "DiAwp+JKAQXqWc2tOPE/U9qg77Y=" + "checksum": "yQDlwrq4/xeG9pH9UtkSbCWd0/o=" } } } \ No newline at end of file diff --git a/src/launcher/GUI/JsonEditorDialog.h b/src/launcher/GUI/JsonEditorDialog.h index a270e8c..4ed8226 100644 --- a/src/launcher/GUI/JsonEditorDialog.h +++ b/src/launcher/GUI/JsonEditorDialog.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -17,6 +17,11 @@ #include #include #include +#include +#include +#include +#include + class JsonParamTableEditor : public QDialog { Q_OBJECT @@ -35,12 +40,24 @@ 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_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 +71,86 @@ 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 { + m_tableView->setStyleSheet(QString(R"( + QTableView { background-color: rgb(%1); font-family: "Microsoft YaHei"; color: #ffffff; gridline-color: #555555; + alternate-background-color: #3a3a3a; } QHeaderView::section { background-color: #0078d7; padding: 4px; font-weight: bold; color: #ffffff; + border: none; } - QTableWidget::item:selected { + QTableView::item { + background-color: #2d2d2d; + color: #ffffff; + } + QTableView::item:selected { background-color: #0078d7; + color: #ffffff; + } + QTableView::item:alternate { + background-color: #3a3a3a; } )").arg(sColor_Blue)); } 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); + // 设置值 + 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 +160,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,15 +182,13 @@ 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; } @@ -165,9 +197,121 @@ private slots: } private: - QTableWidget* m_tableWidget; + QTableView* m_tableView; + QStandardItemModel* m_tableModel; nlohmann::json m_originalJson; // 保存原始JSON以便类型检查 - std::map m_originalTypes; // 保存每个键的原始类型 + std::map m_originalTypes;// 保存每个键的原始类型 + std::map m_editorWidgets;// 保存每个键对应的编辑器控件 + + // 根据类型创建不同的编辑器控件 + QWidget* createEditorWidget(const nlohmann::json& value, JsonValueType type) { + switch (type) { + case JsonValueType::Boolean: { + CircularSwitch* switchBtn = new CircularSwitch(); + switchBtn->setChecked(value.get()); + 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()); + spinBox->setDecimals(0); + } + else { + spinBox->setValue(value.get()); + } + + spinBox->setToolTip(generateTypeHint(type)); + return spinBox; + } + case JsonValueType::String: { + QLineEdit* lineEdit = new QLineEdit(); + lineEdit->setText(QString::fromStdString(value.get())); + 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); + if (it == m_editorWidgets.end()) { + // 没有编辑器控件,使用默认文本处理 + return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg); + } + + QWidget* widget = it->second; + try { + switch (expectedType) { + case JsonValueType::Boolean: { + CircularSwitch* switchBtn = qobject_cast(widget); + if (switchBtn) { + result = switchBtn->isChecked(); + return true; + } + errorMsg = "布尔值控件类型错误"; + return false; + } + case JsonValueType::Number: { + QDoubleSpinBox* spinBox = qobject_cast(widget); + if (spinBox) { + // 检查是否为整数 + double value = spinBox->value(); + if (spinBox->decimals() == 0 && value == floor(value)) { + result = static_cast(value); + } + else { + result = value; + } + return true; + } + errorMsg = "数字控件类型错误"; + return false; + } + case JsonValueType::String: { + QLineEdit* lineEdit = qobject_cast(widget); + if (lineEdit) { + result = lineEdit->text().trimmed().toStdString(); + return true; + } + errorMsg = "字符串控件类型错误"; + return false; + } + default: + // 其他类型使用默认文本处理 + return validateAndConvertValue(getTextFromCell(key), expectedType, result, errorMsg); + } + } + catch (const std::exception& e) { + errorMsg = QString("获取值错误: %1").arg(e.what()); + return false; + } + } + + // 从单元格获取文本值(用于没有专用编辑器的类型) + 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) { diff --git a/src/launcher/GUI/front/pages/displayPageWidget.h b/src/launcher/GUI/front/pages/displayPageWidget.h index b76df9f..458769d 100644 --- a/src/launcher/GUI/front/pages/displayPageWidget.h +++ b/src/launcher/GUI/front/pages/displayPageWidget.h @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/src/launcher/GUI/uiModule/components/sliderSwitch.h b/src/launcher/GUI/uiModule/components/sliderSwitch.h new file mode 100644 index 0000000..0b1378d --- /dev/null +++ b/src/launcher/GUI/uiModule/components/sliderSwitch.h @@ -0,0 +1,287 @@ +#ifndef CIRCULARSWITCH_H +#define CIRCULARSWITCH_H + +#include +#include +#include +#include +#include +#include + +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 \ No newline at end of file