#include "nmWxReservoirProperties.h" #include #include #include #include WxCustomTreeWidget::WxCustomTreeWidget(QWidget* parent) : QTreeWidget(parent) { setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionMode(QAbstractItemView::SingleSelection); m_lastSelected = nullptr; } void WxCustomTreeWidget::mousePressEvent(QMouseEvent* event) { QTreeWidgetItem* item = itemAt(event->pos()); if (item) { // 清除之前选中项的状态 QTreeWidgetItem* prevItem = currentItem(); if (prevItem) { updateRowStyle(prevItem, false); } // 设置新选中项 setCurrentItem(item); // 获取点击的列 int column = header()->logicalIndexAt(event->pos().x()); // 更新行样式 updateRowStyle(item, true, column == 1); // 处理第二列点击 if (QWidget* widget = itemWidget(item, 1)) { widget->setFocus(); } if (column) { if (QWidget* widget = itemWidget(item, 1)) { widget->setFocus(); } } } QTreeWidget::mousePressEvent(event); } void WxCustomTreeWidget::updateRowStyle(QTreeWidgetItem* item, bool selected, bool isValueColumnClicked) { // 第一列字体加粗 item->setFont(0, selected ? QFont("", -1, QFont::Bold) : QFont()); if (QWidget* widget = itemWidget(item, 1)) { // 关键修改1:确保背景绘制顺序正确 //widget->setAttribute(Qt::WA_NoSystemBackground, true); // 禁止系统背景 widget->setAttribute(Qt::WA_TranslucentBackground, true); // 启用透明 // 关键修改2:统一设置样式表 QString style; if (selected) { if (isValueColumnClicked) { // 点击第二列时的样式(有边框) style = //"QWidget { background: transparent; }" "QLineEdit { background: white; }" "QComboBox { background: white; }" "QComboBox::drop-down { font-weight: normal; }"; } else { // 点击第一列时的样式(无边框) style = "QWidget { background: transparent; }" "QLineEdit, QComboBox { background: transparent; font-weight: normal; }" "QComboBox::drop-down { font-weight: normal; }"; } } else { // 非选中状态 style = //"QWidget { background: transparent; }" "QLineEdit, QComboBox { background: white; font-weight: normal; }" "QComboBox::drop-down { font-weight: normal; }"; } widget->setStyleSheet(style); // 强制重绘 //widget->update(); } } //void WxCustomTreeWidget::updateRowStyle(QTreeWidgetItem* item, bool selected, bool isValueColumnClicked) { // // 第一列字体加粗 // QFont font = item->font(0); // font.setBold(selected); // item->setFont(0, font); // // // 第二列控件状态 // if (QWidget* widget = itemWidget(item, 1)) { // // 设置背景 // widget->setAutoFillBackground(true); // QPalette pal = widget->palette(); // pal.setColor(QPalette::Window, // selected ? palette().highlight().color() : palette().base().color()); // widget->setPalette(pal); // // // 设置子控件状态 // if (selected) { // QString style; // if (isValueColumnClicked) { // // 点击第二列时的样式 - 有边框 // style = "QLineEdit { border: 1px solid gray; background: white; font-weight: bold; }" // "QComboBox { border: 1px solid gray; background: white; font-weight: bold; }" // "QComboBox::drop-down { border-left: 1px solid gray; }"; // } else { // // 点击第一列时的样式 - 无边框 // style =/* "QLineEdit { border: none; background: transparent; font-weight: bold; }" // "QComboBox { border: none; background: transparent; font-weight: bold; }" // "QComboBox::drop-down { border: none; }";*/ // "QLineEdit { background: transparent; font-weight: bold; }" // "QComboBox { background: transparent; font-weight: bold; }" // "QComboBox::drop-down { }"; // } // widget->setStyleSheet(style); // } else { // // 非选中状态的样式 // widget->setStyleSheet( // "QLineEdit { background: transparent; font-weight: normal; }" // "QComboBox { background: transparent; font-weight: normal; }" // "QComboBox::drop-down { }" // ); // } // // // 设置焦点状态 // if (isValueColumnClicked) { // if (QLineEdit* edit = widget->findChild()) { // edit->setFocus(); // } // if (QComboBox* combo = widget->findChild()) { // combo->setFocus(); // } // } // } //} // ==================== CustomDelegate 实现 ==================== #include CustomDelegate::CustomDelegate(QObject* parent) : QStyledItemDelegate(parent) { } //void CustomDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, // const QModelIndex& index) const { // // 保存painter状态 // painter->save(); // // // 获取树控件指针(Qt4方式) // const QTreeWidget* treeWidget = qobject_cast(this->parent()); // int treeWidth = treeWidget ? treeWidget->viewport()->width() : option.rect.width() * 2; // // // 绘制选中背景(整行) // if (option.state & QStyle::State_Selected) { // QRect fullRowRect = option.rect; // fullRowRect.setWidth(treeWidth); // painter->fillRect(fullRowRect, option.palette.highlight()); // } // // // 第一列:绘制文本 // if (index.column() == 0) { // // Qt4必须使用initStyleOption初始化才能获取text // QStyleOptionViewItemV4 opt = option; // initStyleOption(&opt, index); // // // 设置字体 // QFont font = opt.font; // if (opt.state & QStyle::State_Selected) { // font.setBold(true); // } // painter->setFont(font); // // // 绘制文本(Qt4必须使用opt.text) // painter->drawText(opt.rect.adjusted(2, 0, -2, 0), // Qt::AlignLeft | Qt::AlignVCenter, // opt.text); // } // // // 恢复painter状态 // painter->restore(); //} void CustomDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { // 保存painter状态 painter->save(); // 获取树控件指针 const QTreeWidget* treeWidget = qobject_cast(this->parent()); int treeWidth = treeWidget ? treeWidget->viewport()->width() : option.rect.width() * 2; // 绘制选中背景(整行) if (option.state & QStyle::State_Selected) { QRect fullRowRect = option.rect; fullRowRect.setWidth(treeWidth); painter->fillRect(fullRowRect, option.palette.highlight()); } // 第一列:绘制文本 if (index.column() == 0) { //Qt4必须使用initStyleOption初始化才能获取text QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); // 设置字体 QFont font = opt.font; if (opt.state & QStyle::State_Selected) { font.setBold(true); } painter->setFont(font); // 绘制文本(Qt4必须使用opt.text) painter->drawText(opt.rect.adjusted(2, 0, -2, 0), Qt::AlignLeft | Qt::AlignVCenter, opt.text); } // 恢复painter状态 painter->restore(); } QSize CustomDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { // 返回默认大小 return QStyledItemDelegate::sizeHint(option, index); } // ==================== BackupManager 实现 ==================== #include #include #include #include #include BackupManager::BackupManager(QObject* parent) : QObject(parent) { } BackupManager::~BackupManager() { qDeleteAll(m_backupMap); } void BackupManager::startEditing(QTreeWidgetItem* item) { if (!m_backupMap.contains(item)) { nmDataAttribute* original = qVariantValue(item->data(1, Qt::UserRole)); if (original) { m_backupMap[item] = new nmDataAttribute(*original); // 标记编辑状态 QWidget* widget = item->treeWidget()->itemWidget(item, 1); if (widget) { widget->setProperty("isEditing", true); } } } } void BackupManager::applyChanges(QTreeWidgetItem* item) { if (m_backupMap.contains(item)) { delete m_backupMap.take(item); // 清除编辑状态 QWidget* widget = item->treeWidget()->itemWidget(item, 1); if (widget) { widget->setProperty("isEditing", false); } } } void BackupManager::cancelEditing(QTreeWidgetItem* item) { if (m_backupMap.contains(item)) { nmDataAttribute* original = qVariantValue(item->data(1, Qt::UserRole)); nmDataAttribute* backup = m_backupMap[item]; if (original && backup) { // 恢复原始值 *original = *backup; // 更新控件显示 QWidget* widget = item->treeWidget()->itemWidget(item, 1); if (widget) { if (QLineEdit* edit = widget->findChild("valueEdit")) { edit->setText(QString::number(original->getValue().toDouble(), 'f', 2)); edit->setFrame(false); edit->setStyleSheet(""); } if (QComboBox* combo = widget->findChild("valueCombo")) { combo->setCurrentIndex(combo->findText(original->getValue().toString())); combo->setFrame(false); } if (QComboBox* combo = widget->findChild("unitCombo")) { combo->setCurrentIndex(combo->findText(original->getUnit())); combo->setFrame(false); } if (QCheckBox* check = widget->findChild("valueCheckBox")) { check->setChecked(original->getValue().toBool()); } widget->setProperty("isEditing", false); } } delete m_backupMap.take(item); } } bool BackupManager::isEditing(QTreeWidgetItem* item) const { return m_backupMap.contains(item); } // ==================== nmWxReservoirProperties 实现 ==================== #include #include #include #include #include #include #include nmWxReservoirProperties::nmWxReservoirProperties(QWidget* parent) : iDlgBase(parent) { resize(700, 500); setupUI(); populateTree(); } nmWxReservoirProperties::~nmWxReservoirProperties() { delete m_pDelegate; delete m_BackupManager; } void nmWxReservoirProperties::setupUI() { QVBoxLayout* mainLayout = new QVBoxLayout(this); // 创建树控件 m_pTreeWidget = new WxCustomTreeWidget(this); m_pTreeWidget->setColumnCount(2); m_pTreeWidget->setHeaderLabels(QStringList() << "Property" << "Value"); //m_pTreeWidget->header()->setStretchLastSection(false); //m_pTreeWidget->header()->setResizeMode(0, QHeaderView::ResizeToContents); //m_pTreeWidget->header()->setResizeMode(1, QHeaderView::Stretch); m_pTreeWidget->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked); m_pTreeWidget->header()->setStretchLastSection(true); // 最后一项充满 //treeWidget.header()->setMovable(false); // 设置列移动 // 设置委托 m_pDelegate = new CustomDelegate(this); m_pTreeWidget->setItemDelegate(m_pDelegate); // 创建备份管理器 m_BackupManager = new BackupManager(this); // 按钮布局 QHBoxLayout* buttonLayout = new QHBoxLayout(); QPushButton* confirmBtn = new QPushButton("Confirm", this); QPushButton* cancelBtn = new QPushButton("Cancel", this); buttonLayout->addStretch(); buttonLayout->addWidget(confirmBtn); buttonLayout->addWidget(cancelBtn); // 设置主布局 mainLayout->addWidget(m_pTreeWidget); mainLayout->addLayout(buttonLayout); // 连接信号槽 connect(m_pTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(onItemClicked(QTreeWidgetItem*, int))); connect(confirmBtn, SIGNAL(clicked()), this, SLOT(onConfirmClicked())); connect(cancelBtn, SIGNAL(clicked()), this, SLOT(onCancelClicked())); } void nmWxReservoirProperties::populateTree() { // 示例1: 带单位的值 nmDataAttribute* lengthAttr = new nmDataAttribute("Length", 100.0, "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "mm" << "cm" << "m" << "km"); lengthAttr->setValueRange(0.1, 10000.0); QTreeWidgetItem* lengthItem = new QTreeWidgetItem(m_pTreeWidget); lengthItem->setText(0, lengthAttr->getName()); QWidget* lengthWidget = new QWidget(); QHBoxLayout* lengthLayout = new QHBoxLayout(lengthWidget); lengthLayout->setMargin(0); lengthLayout->setSpacing(2); QLineEdit* lengthEdit = new QLineEdit(lengthWidget); lengthEdit->setObjectName("valueEdit"); //lengthEdit->setFrame(false); lengthEdit->setText(QString::number(lengthAttr->getValue().toDouble(), 'f', 2)); //lengthEdit->setStyleSheet("background: transparent; border: none;"); //lengthEdit->setAttribute(Qt::WA_TranslucentBackground); QComboBox* unitCombo = new QComboBox(lengthWidget); unitCombo->setObjectName("unitCombo"); //unitCombo->setFrame(false); //unitCombo->setStyleSheet( // "QComboBox { background: transparent; border: none; }" // "QComboBox::drop-down { border: none; }" // ); //unitCombo->setAttribute(Qt::WA_TranslucentBackground); foreach (QString unit, lengthAttr->getListUnitSelections()) { unitCombo->addItem(unit); } lengthLayout->addWidget(lengthEdit); lengthLayout->addWidget(unitCombo); lengthWidget->setAttribute(Qt::WA_TranslucentBackground); lengthWidget->setAutoFillBackground(false); m_pTreeWidget->setItemWidget(lengthItem, 1, lengthWidget); lengthItem->setData(1, Qt::UserRole, qVariantFromValue(lengthAttr)); // 连接信号槽 connect(lengthEdit, SIGNAL(textChanged(QString)), this, SLOT(onLengthValueChanged())); connect(unitCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onLengthUnitChanged())); // 示例2: 下拉选择值 nmDataAttribute* typeAttr = new nmDataAttribute("Type", "Type A", ""); QStringList types; types << "Type A" << "Type B" << "Type C"; typeAttr->setListValueSelections(types); QTreeWidgetItem* typeItem = new QTreeWidgetItem(m_pTreeWidget); typeItem->setText(0, typeAttr->getName()); QComboBox* typeCombo = new QComboBox(); typeCombo->setObjectName("valueCombo"); typeCombo->setFrame(false); foreach (QString type, types) { typeCombo->addItem(type); } typeCombo->setCurrentIndex(typeCombo->findText(typeAttr->getValue().toString())); m_pTreeWidget->setItemWidget(typeItem, 1, typeCombo); typeItem->setData(1, Qt::UserRole, qVariantFromValue(typeAttr)); connect(typeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onTypeChanged())); // 示例3: 布尔值 nmDataAttribute* visibleAttr = new nmDataAttribute("Visible", true, ""); QTreeWidgetItem* visibleItem = new QTreeWidgetItem(m_pTreeWidget); visibleItem->setText(0, visibleAttr->getName()); QCheckBox* visibleCheck = new QCheckBox(); visibleCheck->setObjectName("valueCheckBox"); visibleCheck->setChecked(visibleAttr->getValue().toBool()); m_pTreeWidget->setItemWidget(visibleItem, 1, visibleCheck); visibleItem->setData(1, Qt::UserRole, qVariantFromValue(visibleAttr)); connect(visibleCheck, SIGNAL(stateChanged(int)), this, SLOT(onVisibleChanged())); // 添加到树控件 //m_pTreeWidget->addTopLevelItem(lengthItem); //m_pTreeWidget->addTopLevelItem(typeItem); //m_pTreeWidget->addTopLevelItem(visibleItem); // 展开所有项 m_pTreeWidget->expandAll(); m_pTreeWidget->setColumnWidth(0, m_pTreeWidget->width()/2); m_pTreeWidget->setColumnWidth(1, m_pTreeWidget->width()/2); m_pTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); // 是否可以选择多个项目 m_pTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows);// 设置选择行或者列 } void nmWxReservoirProperties::onLengthValueChanged() { QTreeWidgetItem* item = m_pTreeWidget->currentItem(); if (!item) return; QWidget* widget = m_pTreeWidget->itemWidget(item, 1); QLineEdit* edit = widget->findChild("valueEdit"); QComboBox* unitCombo = widget->findChild("unitCombo"); nmDataAttribute* attr = qVariantValue(item->data(1, Qt::UserRole)); if (attr && edit && unitCombo) { // 直接设置值,nmDataAttribute内部会处理单位转换 attr->setValue(edit->text().toDouble()); // 验证值有效性 if (!attr->isValueValid()) { // 禁止编辑下拉框 unitCombo->setEnabled(false); edit->setStyleSheet("color: red;"); } else { unitCombo->setEnabled(true); edit->setStyleSheet(""); } } } void nmWxReservoirProperties::onLengthUnitChanged() { QTreeWidgetItem* item = m_pTreeWidget->currentItem(); if (!item) return; QWidget* widget = m_pTreeWidget->itemWidget(item, 1); QLineEdit* edit = widget->findChild("valueEdit"); QComboBox* unitCombo = widget->findChild("unitCombo"); nmDataAttribute* attr = qVariantValue(item->data(1, Qt::UserRole)); if (attr && edit && unitCombo) { QString newUnit = unitCombo->currentText(); // // 改变单位 // if (attr->setUnit(newUnit)) { // // 更新显示值 // double newValue = attr->getValue().toDouble(); // edit->setText(QString::number(newValue, 'f', 2)); // // 重新验证值 // if (!attr->isValueValid()) { // edit->setStyleSheet("color: red;"); // } else { // edit->setStyleSheet(""); // } // } } } void nmWxReservoirProperties::onTypeChanged() { QTreeWidgetItem* item = m_pTreeWidget->currentItem(); if (!item) return; QComboBox* combo = m_pTreeWidget->itemWidget(item, 1)->findChild("valueCombo"); nmDataAttribute* attr = qVariantValue(item->data(1, Qt::UserRole)); if (attr && combo) { attr->setValue(combo->currentText()); } } void nmWxReservoirProperties::onVisibleChanged() { QTreeWidgetItem* item = m_pTreeWidget->currentItem(); if (!item) return; QCheckBox* check = m_pTreeWidget->itemWidget(item, 1)->findChild("valueCheckBox"); nmDataAttribute* attr = qVariantValue(item->data(1, Qt::UserRole)); if (attr && check) { attr->setValue(check->isChecked()); } } //void nmWxReservoirProperties::onItemClicked(QTreeWidgetItem* item, int column) { // QWidget* widget = m_pTreeWidget->itemWidget(item, 1); // if (!widget) return; // // if (column == 1) { // m_BackupManager->startEditing(item); // } //} void nmWxReservoirProperties::onItemClicked(QTreeWidgetItem* item, int column) { QWidget* widget = m_pTreeWidget->itemWidget(item, 1); if (!widget) return; if (column == 1) { m_BackupManager->startEditing(item); // 设置焦点到第二列的控件 if (QLineEdit* edit = widget->findChild()) { edit->setFocus(); } else if (QComboBox* combo = widget->findChild()) { combo->setFocus(); } else if (QCheckBox* check = widget->findChild()) { check->setFocus(); } } } //void nmWxReservoirProperties::onItemClicked(QTreeWidgetItem* item, int column) { // QWidget* widget = m_pTreeWidget->itemWidget(item, 1); // if (!widget) return; // // if (column == 1) { // // 进入编辑状态 - 显示边框 // QLineEdit* edit = widget->findChild("valueEdit"); // if (edit) { // edit->setFrame(true); // edit->setFocus(); // } // // QComboBox* combo = widget->findChild("valueCombo"); // if (combo) { // combo->setFrame(true); // combo->setFocus(); // } // // combo = widget->findChild("unitCombo"); // if (combo) { // combo->setFrame(true); // } // // m_BackupManager->startEditing(item); // } else { // // 退出编辑状态 - 隐藏边框 // QLineEdit* edit = widget->findChild("valueEdit"); // if (edit) edit->setFrame(false); // // QComboBox* combo = widget->findChild("valueCombo"); // if (combo) combo->setFrame(false); // // combo = widget->findChild("unitCombo"); // if (combo) combo->setFrame(false); // } //} //void nmWxReservoirProperties::setupTreeItem(QTreeWidgetItem* item, nmDataAttribute* attr) { // item->setText(0, attr->getName()); // m_pTreeWidget->addTopLevelItem(item); // // QWidget* widget = new QWidget(); // QHBoxLayout* layout = new QHBoxLayout(widget); // layout->setMargin(0); // layout->setSpacing(2); // // if (!attr->getListValueSelections().isEmpty()) { // QComboBox* combo = new QComboBox(widget); // combo->addItems(attr->getListValueSelections()); // combo->setCurrentIndex(combo->findText(attr->getValue().toString())); // layout->addWidget(combo); // } // else if (attr->getValue().type() == QVariant::Bool) { // QCheckBox* check = new QCheckBox(widget); // check->setChecked(attr->getValue().toBool()); // layout->addWidget(check); // } // else { // QLineEdit* edit = new QLineEdit(widget); // edit->setObjectName("valueEdit"); // edit->setFrame(false); // edit->setText(QString::number(lengthAttr->convertTo("m"), 'f', 2)); // layout->addWidget(edit); // // if (!attr->getListUnitSelections().isEmpty()) { // QComboBox* unitCombo = new QComboBox(widget); // unitCombo->setObjectName("unitCombo"); // unitCombo->addItems(attr->getListUnitSelections()); // unitCombo->setCurrentIndex(unitCombo->findText(attr->getUnit())); // layout->addWidget(unitCombo); // } // } // // m_pTreeWidget->setItemWidget(item, 1, widget); // item->setData(1, Qt::UserRole, qVariantFromValue(attr)); // // // 安装事件过滤器 // TreeItemEventFilter* filter = new TreeItemEventFilter(item, this); // widget->installEventFilter(filter); // foreach(QWidget* child, widget->findChildren()) { // child->installEventFilter(filter); // } // connect(filter, &TreeItemEventFilter::controlFocused, // this, &nmWxReservoirProperties::onControlFocused); // m_eventFilters.append(filter); //} void nmWxReservoirProperties::onConfirmClicked() { // 确认修改 if (QTreeWidgetItem* item = m_pTreeWidget->currentItem()) { m_BackupManager->applyChanges(item); } accept(); } void nmWxReservoirProperties::onCancelClicked() { // 取消修改 if (QTreeWidgetItem* item = m_pTreeWidget->currentItem()) { m_BackupManager->cancelEditing(item); } reject(); } //void nmWxReservoirProperties::setupTreeItem(QTreeWidgetItem* item, nmDataAttribute* attr) { // item->setText(0, attr->getName()); // m_pTreeWidget->addTopLevelItem(item); // // QWidget* widget = new QWidget(); // QHBoxLayout* layout = new QHBoxLayout(widget); // layout->setMargin(0); // layout->setSpacing(2); // // if (!attr->getListValueSelections().isEmpty()) { // QComboBox* combo = new QComboBox(widget); // combo->addItems(attr->getListValueSelections()); // combo->setCurrentIndex(combo->findText(attr->getValue().toString())); // layout->addWidget(combo); // } // else if (attr->getValue().type() == QVariant::Bool) { // QCheckBox* check = new QCheckBox(widget); // check->setChecked(attr->getValue().toBool()); // layout->addWidget(check); // } // else { // QLineEdit* edit = new QLineEdit(widget); // edit->setText(QString::number(attr->convertTo(attr->getUnit()))); // layout->addWidget(edit); // // if (!attr->getListUnitSelections().isEmpty()) { // QComboBox* unitCombo = new QComboBox(widget); // unitCombo->addItems(attr->getListUnitSelections()); // unitCombo->setCurrentIndex(unitCombo->findText(attr->getUnit())); // layout->addWidget(unitCombo); // } // } // // m_pTreeWidget->setItemWidget(item, 1, widget); // item->setData(1, Qt::UserRole, qVariantFromValue(attr)); // // // 安装事件过滤器 // TreeItemEventFilter* filter = new TreeItemEventFilter(item, this); // widget->installEventFilter(filter); // foreach(QWidget* child, widget->findChildren()) { // child->installEventFilter(filter); // } // connect(filter, SIGNAL(controlFocused(QTreeWidgetItem*)), // this, SLOT(onControlFocused(QTreeWidgetItem*))); // m_eventFilters.append(filter); //} // //void nmWxReservoirProperties::onControlFocused(QTreeWidgetItem* item) { // static_cast(m_pTreeWidget)->updateRowStyle(item, true, true); //} // //void nmWxReservoirProperties::onItemClicked(QTreeWidgetItem* item, int column) { // static_cast(m_pTreeWidget)->updateRowStyle(item, true, column == 1); //}