From b2904c211e17359c117cb02911fa7c075730575b Mon Sep 17 00:00:00 2001 From: gaozheng Date: Thu, 25 Jun 2026 19:50:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(vtk):=20=E5=9D=90=E6=A0=87=E8=BD=B4?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E9=A2=84=E7=83=AD(4a)+=E8=A3=85=E7=BD=AE?= =?UTF-8?q?=E6=9E=9A=E4=B8=BE=E5=88=B0=E8=BE=BE=E9=87=8D=E5=88=B7=E4=B8=8B?= =?UTF-8?q?=E6=8B=89+=E6=A0=91=E2=86=92VTK=E9=80=89=E4=B8=AD=E8=81=94?= =?UTF-8?q?=E5=8A=A8=E6=AD=A3=E5=90=91(=E2=91=A1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 4a 坐标轴面板首开卡顿:启动时 ensurePolished+adjustSize 预热样式/布局,避免首次点开同步解析卡UI - 装置下拉空:枚举异步加载(可能晚于数据)→在 listArrayTypes 回调里 refreshArrayFilters 重填各段下拉 - ② 树选中切片/异常→VTK高亮:CategorySection 发 datasetSelected→main 对 dd_anomaly setSelectedAnomaly /dd_slice selectSavedSlice。反向(VTK→树)需拾取回调,并入 OPT-002 构建:app 链接通过 --- src/app/main.cpp | 19 ++++++++++++++++++- .../panels/columns/CategoryAnalysisTab.cpp | 5 +++++ .../panels/columns/CategoryAnalysisTab.hpp | 2 ++ src/app/panels/columns/CategorySection.cpp | 9 +++++++++ src/app/panels/columns/CategorySection.hpp | 2 ++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index 6091dac..723370e 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -368,7 +368,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re auto* drawer = new geopro::app::ColumnDrawer(centerWidget, fieldDict); auto* viewToolbar = new geopro::app::VtkViewToolbar(centerWidget); // VTK 画布全局视图控制竖排工具条 // 拉装置类型枚举(全局,登录后一次)→ 填字典;电阻率/视电阻率段装置下拉据此显示 + 过滤(spec §6/§10)。 - cmdRepo.listArrayTypes([fieldDict](bool ok, QJsonArray list, QString) { + cmdRepo.listArrayTypes([fieldDict, drawer](bool ok, QJsonArray list, QString) { if (!ok) return; std::map e; for (const auto& v : list) { @@ -378,6 +378,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re if (!iv.empty()) e[iv] = o.value(QStringLiteral("name")).toString().toStdString(); } fieldDict->setArrayTypeEnum(std::move(e)); + // 枚举到达(异步,可能晚于已加载的数据)→ 重填各段装置下拉,避免下拉为空。 + drawer->analysisTab()->refreshArrayFilters(); }); // 左侧抽屉 | 右侧画布用 QSplitter(左面板可拖改宽);工具条悬浮于画布上(不占布局)。 auto* split = new QSplitter(Qt::Horizontal); @@ -397,6 +399,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re // 坐标轴设置抽屉面板:叠加 vtkWidget、工具条右侧滑出,默认隐藏(点设置 toggle)。 auto* axesPanel = new geopro::app::AxesSettingsPanel(vtkWidget); axesPanel->hide(); + // 预热:首次打开前先完成样式表解析 + 布局尺寸计算(含 spinbox/滑块/中文标签首次字体解析), + // 避免用户第一次点开时同步做这些导致 UI 卡顿。 + axesPanel->ensurePolished(); + axesPanel->adjustSize(); // 3b:三维分析栏勾选的已保存切片(dd_slice) id 集合 + 调和函数。 // syncSlices:按"当前活动体 dsId"调和 InteractionManager 上显示的已保存切片—— @@ -912,6 +918,17 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re sceneView->setAnomalyVisible(id.toStdString(), vis); renderWindowPtr->Render(); }); + // 树选中切片/异常 → VTK 高亮联动(正向 list→VTK;反向 VTK→list 需拾取回调,见 OPT-002)。 + QObject::connect(analysisTab, &geopro::app::CategoryAnalysisTab::datasetSelected, vtkWidget, + [sceneView, interactionMgr, renderWindowPtr](const QString& dsId, + const QString& ddCode) { + const std::string id = dsId.toStdString(); + if (ddCode == QStringLiteral("dd_anomaly")) + sceneView->setSelectedAnomaly(id); + else if (ddCode == QStringLiteral("dd_slice")) + interactionMgr->selectSavedSlice(id); // 选中已渲染的该切片(高亮) + renderWindowPtr->Render(); + }); // 异常双击属性(R83)/右键删除已并入 analysisTab 的 detailRequested(dd_anomaly) / // deleteDatasetRequested(dd_anomaly);列表选中→VTK高亮(R84)随旧栏退役暂缺,待新段补 anomalySelected。 diff --git a/src/app/panels/columns/CategoryAnalysisTab.cpp b/src/app/panels/columns/CategoryAnalysisTab.cpp index f9adedf..4e7c0ee 100644 --- a/src/app/panels/columns/CategoryAnalysisTab.cpp +++ b/src/app/panels/columns/CategoryAnalysisTab.cpp @@ -49,6 +49,7 @@ CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* d &CategoryAnalysisTab::sliceExportDatRequested); connect(sec, &CategorySection::anomalyVisibilityChanged, this, &CategoryAnalysisTab::anomalyVisibilityChanged); + connect(sec, &CategorySection::datasetSelected, this, &CategoryAnalysisTab::datasetSelected); // #7:各段等分 stretch → 内容都少时四段平分高度填满面板(初始与 VTK 区等高、不出滚动条); // 某段内容增多时其最小高度(=内容总高)撑大,超出视口则由外层 QScrollArea 统一出纵向滚动条。 col->addWidget(sec, 1); @@ -71,6 +72,10 @@ void CategoryAnalysisTab::setStructure(const std::vectorsetStructure(nodes); } +void CategoryAnalysisTab::refreshArrayFilters() { + for (auto& [id, sec] : sections_) sec->refreshArrayFilter(); +} + CategorySection* CategoryAnalysisTab::section(const std::string& id) const { const auto it = sections_.find(id); return it != sections_.end() ? it->second : nullptr; diff --git a/src/app/panels/columns/CategoryAnalysisTab.hpp b/src/app/panels/columns/CategoryAnalysisTab.hpp index 42c8335..f32a096 100644 --- a/src/app/panels/columns/CategoryAnalysisTab.hpp +++ b/src/app/panels/columns/CategoryAnalysisTab.hpp @@ -25,6 +25,7 @@ public: void setBuckets(const CategoryBuckets& b); // 分发到 5 段(与 categoryConfigs 同序) void setStructure(const std::vector& nodes); // 转发各段 + void refreshArrayFilters(); // 装置枚举异步加载后,重填各段装置筛选下拉 CategorySection* section(const std::string& id) const; // 按 CategorySpec.id 取段 signals: @@ -40,6 +41,7 @@ signals: void sliceExportImageRequested(const QString& dsId); void sliceExportDatRequested(const QString& dsId); void anomalyVisibilityChanged(const QString& dsId, bool vis); + void datasetSelected(const QString& dsId, const QString& ddCode); // 树选中→VTK 高亮联动 private: void recomputeCheckedUnion(); diff --git a/src/app/panels/columns/CategorySection.cpp b/src/app/panels/columns/CategorySection.cpp index 413a4d9..c1242c1 100644 --- a/src/app/panels/columns/CategorySection.cpp +++ b/src/app/panels/columns/CategorySection.cpp @@ -101,6 +101,15 @@ CategorySection::CategorySection(const CategorySpec& spec, geopro::data::Dataset if (spec_.id == "voxel") { // 仅三维体段提供右键操作菜单(体/切片/异常) list_->setContextMenuPolicy(Qt::CustomContextMenu); connect(list_, &QTreeWidget::customContextMenuRequested, this, &CategorySection::showContextMenu); + // 树选中切片/异常 → VTK 高亮联动(正向 list→VTK)。 + connect(list_, &QTreeWidget::itemSelectionChanged, this, [this] { + const auto items = list_->selectedItems(); + if (items.isEmpty()) return; + QTreeWidgetItem* it = items.first(); + const QString id = it->data(0, kDsIdRole).toString(); + const QString dd = it->data(0, kDsDdCodeRole).toString(); + if (!id.isEmpty() && dd != QStringLiteral("container")) emit datasetSelected(id, dd); + }); } body->addWidget(list_, 1); diff --git a/src/app/panels/columns/CategorySection.hpp b/src/app/panels/columns/CategorySection.hpp index 1c0e5c1..c25ad18 100644 --- a/src/app/panels/columns/CategorySection.hpp +++ b/src/app/panels/columns/CategorySection.hpp @@ -34,6 +34,7 @@ public: void setDatasets(const std::vector& rows); void setChecked(const QString& dsId, bool on); // 按 dsId 勾选/取消(新建切片自动勾选等场景) QStringList checkedIds() const { return checkedDsIds(); } // 当前勾选 ds(异常显隐同步用) + void refreshArrayFilter() { refreshArrayCombo(); } // 装置枚举异步加载后重填下拉 const CategorySpec& spec() const { return spec_; } signals: @@ -49,6 +50,7 @@ signals: void sliceExportImageRequested(const QString& dsId); // 切片→导出图片 void sliceExportDatRequested(const QString& dsId); // 切片→导出 dat void anomalyVisibilityChanged(const QString& dsId, bool vis); // 异常→显示/隐藏 + void datasetSelected(const QString& dsId, const QString& ddCode); // 树选中行→VTK 高亮联动(切片/异常) private: void showContextMenu(const QPoint& pos); // 段体树右键菜单(详情 + 删除)