From 9bb93ec8583b5cbd2f53eb8b1a7023e63ee71ea8 Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Thu, 8 Oct 2026 16:40:43 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(nmNum):=20=E5=A2=9E=E5=8A=A0=20PEBI=20?= =?UTF-8?q?=E7=BD=91=E6=A0=BC=E5=9B=9B=E7=A7=8D=E6=98=BE=E7=A4=BA=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 扩展通用 MeshLayer 的点、线框、表面和轮廓模式 - 为网格预览和结果视图增加独立显示模式控制 - 冻结动画导出的网格显示模式并校验请求 - 补充中文翻译 --- Bin/Config/Lang/cn/nmNum_cn.qm | Bin 157817 -> 158443 bytes Bin/Config/Lang/cn/nmNum_cn.ts | 10 +++ Include/nmNum/nmRender/nmVTKMeshLayer.h | 8 +- .../nmSubWxs/nmPebiGridSceneController.h | 6 ++ .../nmSubWxs/nmPebiResultAnimationExporter.h | 3 + .../nmSubWxs/nmPebiResultSceneController.h | 6 ++ .../nmNum/nmSubWxs/nmWxPebiGridViewWidget.h | 8 +- .../nmNum/nmSubWxs/nmWxPebiResultControlBar.h | 4 + Src/nmNum/nmRender/nmVTKMeshLayer.cpp | 39 +++++++-- .../nmSubWxs/nmPebiGridSceneController.cpp | 61 ++++++++++--- .../nmPebiResultAnimationExporter.cpp | 11 ++- .../nmSubWxs/nmPebiResultSceneController.cpp | 63 ++++++++++++-- Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp | 81 +++++++++++++++++- .../nmSubWxs/nmWxPebiResultControlBar.cpp | 81 ++++++++++++++++++ .../nmSubWxs/nmWxPebiResultViewWidget.cpp | 9 +- 15 files changed, 357 insertions(+), 33 deletions(-) diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 594a836b037a1c00bfc0bf0f15e8d7275608d7eb..9fbf221573fcae9bbff431cb9bc4c5fdd0b2482e 100644 GIT binary patch delta 5560 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 cY|d}By>mbNly^z@tkccI`GH;11QOm9{>OV diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index d669c20a..aae1c227 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -2930,6 +2930,11 @@ Reason: %1 nmWxPebiResultControlBar + Display显示 + Point点 + Wireframe线框 + Surface表面 + Contour轮廓 Property属性 Display property显示属性 Color settings颜色设置 @@ -2999,6 +3004,11 @@ Reason: %1 nmWxPebiGridViewWidget + Display显示 + Point点 + Wireframe线框 + Surface表面 + Contour轮廓 No grid data.暂无网格数据。 Scale Grid比例网格 The grid preview data is invalid.网格预览数据无效。 diff --git a/Include/nmNum/nmRender/nmVTKMeshLayer.h b/Include/nmNum/nmRender/nmVTKMeshLayer.h index e747d2bc..23e4ce77 100644 --- a/Include/nmNum/nmRender/nmVTKMeshLayer.h +++ b/Include/nmNum/nmRender/nmVTKMeshLayer.h @@ -25,7 +25,9 @@ public: enum DisplayMode { DisplayMode_Surface = 0, ///< 只显示填充表面。 - DisplayMode_SurfaceWithEdges ///< 同时显示表面和单元边线。 + DisplayMode_SurfaceWithEdges = 1, ///< 同时显示表面和单元边线。 + DisplayMode_Point = 2, ///< 显示 Mapper 实际可渲染的原始顶点。 + DisplayMode_Wireframe = 3 ///< 以线框方式显示网格单元。 }; enum ScalarAssociation @@ -75,7 +77,9 @@ public: /** @brief 返回当前直接数据或管线输出数据集的非所有权指针。 */ vtkDataSet* getDataSet() const; - /** @brief 设置表面或表面加边线显示模式。 */ + /** @brief 判断枚举值是否为受支持的网格显示模式。 */ + static bool isValidDisplayMode(DisplayMode eMode); + /** @brief 设置点、线框、表面或表面加边线显示模式。 */ void setDisplayMode(DisplayMode eMode); /** @brief 返回当前显示模式。 */ DisplayMode getDisplayMode() const; diff --git a/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h b/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h index 4b5961a7..a3224a22 100644 --- a/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h +++ b/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h @@ -2,6 +2,7 @@ #define NMPEBIGRIDSCENECONTROLLER_H #include "nmSubWxs_global.h" +#include "nmVTKMeshLayer.h" #include @@ -29,6 +30,11 @@ public: /** @brief 解除网格引用并隐藏图层,不销毁 Scene 或 Renderer。 */ void clear(); + /** @brief 设置本窗口网格显示模式;无有效数据时只保存偏好。 */ + void setMeshDisplayMode(nmVTKMeshLayer::DisplayMode eMode); + /** @brief 返回本窗口网格显示模式偏好。 */ + nmVTKMeshLayer::DisplayMode getMeshDisplayMode() const; + /** @brief 切换 XY 坐标比例网格。 */ void setBoundsGridVisible(bool bVisible); diff --git a/Include/nmNum/nmSubWxs/nmPebiResultAnimationExporter.h b/Include/nmNum/nmSubWxs/nmPebiResultAnimationExporter.h index 08c5fc9d..25f20ec1 100644 --- a/Include/nmNum/nmSubWxs/nmPebiResultAnimationExporter.h +++ b/Include/nmNum/nmSubWxs/nmPebiResultAnimationExporter.h @@ -4,6 +4,7 @@ #include "nmSubWxs_global.h" #include "nmPebiResultAnimationExportSettings.h" #include "nmPebiResultDisplaySettings.h" +#include "nmVTKMeshLayer.h" #include #include @@ -60,6 +61,8 @@ public: bool m_bGradientBackground; /** @brief 当前屏幕相机的深拷贝,导出器不会修改屏幕相机。 */ vtkSmartPointer m_pCamera; + /** @brief 开始导出前冻结的网格显示模式。 */ + nmVTKMeshLayer::DisplayMode m_eMeshDisplayMode; }; /** @param pParent Qt父对象,不参与VTK资源所有权。 */ diff --git a/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h b/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h index a85c8464..c8324ddb 100644 --- a/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h +++ b/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h @@ -3,6 +3,7 @@ #include "nmSubWxs_global.h" #include "nmPebiResultDisplaySettings.h" +#include "nmVTKMeshLayer.h" #include #include @@ -71,6 +72,11 @@ public: const nmPebiResultDisplaySettings& oSettings, QString* pError = nullptr); + /** @brief 设置本窗口网格显示模式;无有效快照时只保存偏好。 */ + void setMeshDisplayMode(nmVTKMeshLayer::DisplayMode eMode); + /** @brief 返回本窗口网格显示模式偏好。 */ + nmVTKMeshLayer::DisplayMode getMeshDisplayMode() const; + /** @brief 设置色标显隐;默认显示,偏好跨快照保留。 */ void setScalarBarVisible(bool bVisible); /** @brief 设置平面比例网格显隐;偏好跨快照保留。 */ diff --git a/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h b/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h index ba110cbd..9da66ff5 100644 --- a/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h +++ b/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h @@ -6,6 +6,7 @@ #include class QAction; +class QComboBox; class QLabel; class QMenu; class QToolBar; @@ -17,7 +18,7 @@ class nmWxVTKRenderContainerWidget; /** * @brief 二维 PEBI 网格预览业务组合控件。 * - * 本类定位为网格几何检查窗口,只显示固定灰色表面、黑色单元边线和 + * 本类定位为网格几何检查窗口,支持点、线框、表面和轮廓四种模式及 * 可选的 XY 比例网格,不解释输入数据中的历史属性数组。右侧工具栏和 * 右键菜单复用同一批 QAction;通用导航、旋转中心、截图和打印能力由 * 内部 nmRender 容器提供,不继承业务视图基类。 @@ -48,6 +49,8 @@ public: bool hasViewData() const; private slots: + /** @brief 从 itemData 读取并提交当前窗口的网格显示模式。 */ + void onDisplayModeIndexChanged(int nIndex); /** @brief 切换世界坐标中的 XY 比例网格,不改变相机。 */ void onBoundsGridToggled(bool bVisible); /** @brief 向通用右键菜单追加本窗口独占的比例网格动作。 */ @@ -60,6 +63,8 @@ private: void createUi(); /** @brief 恢复无数据时的比例网格偏好和底栏文字。 */ void resetControls(); + /** @brief 从 SceneController 镜像显示模式,且不触发用户选择槽。 */ + void synchronizeDisplayModeFromScene(); /** @brief 统一启停依赖有效网格的业务动作。 */ void setControlsEnabled(bool bEnabled); @@ -67,6 +72,7 @@ private: nmPebiGridSceneController* m_pSceneController; ///< 本类独占,必须先于容器销毁。 QToolBar* m_pToolBar; ///< Qt 父对象拥有的右侧竖向工具栏。 QAction* m_pBoundsGridAction; ///< 工具栏和右键菜单共享的比例网格动作。 + QComboBox* m_pDisplayModeCombo; ///< 显示模式框,itemData 保存 DisplayMode 枚举值。 QLabel* m_pGridInfoLabel; ///< 底栏左侧的网格类型、单元数和平面信息。 QLabel* m_pStatusLabel; ///< 建网失败且保留旧网格时使用的黄色提示栏。 bool m_bHasViewData; ///< 与场景控制器的成功数据状态保持同步。 diff --git a/Include/nmNum/nmSubWxs/nmWxPebiResultControlBar.h b/Include/nmNum/nmSubWxs/nmWxPebiResultControlBar.h index 9b4c92e1..13a93a4a 100644 --- a/Include/nmNum/nmSubWxs/nmWxPebiResultControlBar.h +++ b/Include/nmNum/nmSubWxs/nmWxPebiResultControlBar.h @@ -56,6 +56,8 @@ signals: void exportAnimationRequested(); private slots: + /** @brief 用户选择显示模式时提交 itemData 中的 DisplayMode 枚举值。 */ + void onDisplayModeIndexChanged(int nIndex); /** @brief 用户选择属性时提交稳定属性 ID。 */ void onPropertyIndexChanged(int nIndex); /** @brief 用户选择时间时提交 itemData 中的零基帧。 */ @@ -100,6 +102,8 @@ private: nmPebiResultPlaybackController* m_pPlaybackController; /** @brief 已渲染属性、帧和显示设置的唯一真源;本控件不拥有。 */ nmPebiResultSceneController* m_pSceneController; + /** @brief 显示模式选择框,条目数据保存 DisplayMode 枚举值。 */ + QComboBox* m_pDisplayModeCombo; /** @brief 属性选择框,条目数据保存稳定英文属性 ID。 */ QComboBox* m_pPropertyCombo; /** @brief 使用固定色带图标打开颜色设置对话框。 */ diff --git a/Src/nmNum/nmRender/nmVTKMeshLayer.cpp b/Src/nmNum/nmRender/nmVTKMeshLayer.cpp index b6d7bbcf..44d943cd 100644 --- a/Src/nmNum/nmRender/nmVTKMeshLayer.cpp +++ b/Src/nmNum/nmRender/nmVTKMeshLayer.cpp @@ -52,6 +52,8 @@ nmVTKMeshLayer::nmVTKMeshLayer(const QString& sLayerId) m_pActor->SetMapper(m_pMapper); m_pActor->GetProperty()->SetRepresentationToSurface(); m_pActor->GetProperty()->EdgeVisibilityOff(); + m_pActor->GetProperty()->SetPointSize(3.0f); + m_pActor->GetProperty()->SetLineWidth(1.0f); setRenderProp(m_pActor); } @@ -208,6 +210,14 @@ vtkDataSet* nmVTKMeshLayer::getDataSet() const return getInputDataSet(false); } +bool nmVTKMeshLayer::isValidDisplayMode(DisplayMode eMode) +{ + return eMode == DisplayMode_Surface || + eMode == DisplayMode_SurfaceWithEdges || + eMode == DisplayMode_Point || + eMode == DisplayMode_Wireframe; +} + void nmVTKMeshLayer::setDisplayMode(DisplayMode eMode) { Q_ASSERT(isMeshLayerGuiThread()); @@ -215,13 +225,30 @@ void nmVTKMeshLayer::setDisplayMode(DisplayMode eMode) return; } - // 未识别枚举值按纯表面处理,避免把无效值带入 VTK Property。 - m_eDisplayMode = eMode == DisplayMode_SurfaceWithEdges - ? DisplayMode_SurfaceWithEdges : DisplayMode_Surface; + // 未识别枚举值仍按纯表面处理,保持旧接口的降级语义。 + m_eDisplayMode = isValidDisplayMode(eMode) + ? eMode : DisplayMode_Surface; vtkProperty* pProperty = m_pActor->GetProperty(); - pProperty->SetRepresentationToSurface(); - pProperty->SetEdgeVisibility( - m_eDisplayMode == DisplayMode_SurfaceWithEdges ? 1 : 0); + pProperty->SetPointSize(3.0f); + pProperty->SetLineWidth(1.0f); + pProperty->EdgeVisibilityOff(); + + switch(m_eDisplayMode) { + case DisplayMode_Point: + pProperty->SetRepresentationToPoints(); + break; + case DisplayMode_Wireframe: + pProperty->SetRepresentationToWireframe(); + break; + case DisplayMode_SurfaceWithEdges: + pProperty->SetRepresentationToSurface(); + pProperty->EdgeVisibilityOn(); + break; + case DisplayMode_Surface: + default: + pProperty->SetRepresentationToSurface(); + break; + } } nmVTKMeshLayer::DisplayMode nmVTKMeshLayer::getDisplayMode() const diff --git a/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp b/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp index 28cb766d..ff59a18f 100644 --- a/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp @@ -52,11 +52,31 @@ public: : m_pContainer(pRenderContainer), m_pMeshLayer(nullptr), m_pPlanarScaleGridLayer(nullptr), + m_eMeshDisplayMode( + nmVTKMeshLayer::DisplayMode_SurfaceWithEdges), m_bBoundsGridVisible(false), m_bHasData(false) { } + /** @brief 将窗口偏好应用到现有网格 Actor,不触发渲染。 */ + void applyMeshDisplayModeWithoutRender() + { + if(m_pMeshLayer == nullptr) { + return; + } + + m_pMeshLayer->setDisplayMode(m_eMeshDisplayMode); + vtkProperty* pProperty = m_pMeshLayer->getActor()->GetProperty(); + const bool bUseBlackColor = + m_eMeshDisplayMode == nmVTKMeshLayer::DisplayMode_Point || + m_eMeshDisplayMode == + nmVTKMeshLayer::DisplayMode_Wireframe; + const double dColor = bUseBlackColor ? 0.0 : 211.0 / 255.0; + pProperty->SetColor(dColor, dColor, dColor); + pProperty->SetEdgeColor(0.0, 0.0, 0.0); + } + bool ensureBaseLayers() { nmVTKScene* pScene = m_pContainer != nullptr @@ -76,14 +96,9 @@ public: return false; } m_pMeshLayer = pLayer; - // PEBI 预览固定使用稳定灰色表面和黑色单元边线。 - m_pMeshLayer->getActor()->GetProperty()->SetColor( - 211.0 / 255.0, 211.0 / 255.0, - 211.0 / 255.0); - m_pMeshLayer->getActor()->GetProperty()->SetEdgeColor( - 0.0, 0.0, 0.0); - // 仅关闭当前 PEBI 预览 Actor 的光照,避免固定面色随视角变化。 + // 关闭光照,保证各显示模式的固定黑色或灰色不随视角变化。 m_pMeshLayer->getActor()->GetProperty()->LightingOff(); + applyMeshDisplayModeWithoutRender(); } if(m_pPlanarScaleGridLayer == nullptr) { @@ -113,10 +128,9 @@ public: m_oViewData.clear(); return false; } - // 输入可能包含历史数组,网格预览始终关闭标量着色并显示单元边线。 + // 输入可能包含历史数组,网格预览始终关闭标量着色。 m_pMeshLayer->setScalarVisibility(false); - m_pMeshLayer->setDisplayMode( - nmVTKMeshLayer::DisplayMode_SurfaceWithEdges); + applyMeshDisplayModeWithoutRender(); m_pMeshLayer->setVisible(true); if(!m_pPlanarScaleGridLayer->setBounds( @@ -161,6 +175,7 @@ public: nmVTKMeshLayer* m_pMeshLayer; ///< Scene 所有,控制器只观察。 nmVTKPlanarScaleGridLayer* m_pPlanarScaleGridLayer; ///< Scene 所有。 nmPebiGridViewData m_oViewData; + nmVTKMeshLayer::DisplayMode m_eMeshDisplayMode; ///< 本窗口显示偏好。 bool m_bBoundsGridVisible; bool m_bHasData; }; @@ -253,6 +268,31 @@ void nmPebiGridSceneController::clear() m_pPrivate->m_bBoundsGridVisible = false; } +void nmPebiGridSceneController::setMeshDisplayMode( + nmVTKMeshLayer::DisplayMode eMode) +{ + if(m_pPrivate == nullptr || + !nmVTKMeshLayer::isValidDisplayMode(eMode) || + m_pPrivate->m_eMeshDisplayMode == eMode) { + return; + } + + m_pPrivate->m_eMeshDisplayMode = eMode; + m_pPrivate->applyMeshDisplayModeWithoutRender(); + if(m_pPrivate->m_bHasData && + m_pPrivate->m_pContainer != nullptr) { + m_pPrivate->m_pContainer->renderView(); + } +} + +nmVTKMeshLayer::DisplayMode +nmPebiGridSceneController::getMeshDisplayMode() const +{ + return m_pPrivate != nullptr + ? m_pPrivate->m_eMeshDisplayMode + : nmVTKMeshLayer::DisplayMode_SurfaceWithEdges; +} + void nmPebiGridSceneController::setBoundsGridVisible(bool bVisible) { if(m_pPrivate == nullptr) { @@ -264,6 +304,7 @@ void nmPebiGridSceneController::setBoundsGridVisible(bool bVisible) bVisible && m_pPrivate->m_bHasData); } if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != nullptr) { + m_pPrivate->applyMeshDisplayModeWithoutRender(); m_pPrivate->m_pContainer->renderView(); } } diff --git a/Src/nmNum/nmSubWxs/nmPebiResultAnimationExporter.cpp b/Src/nmNum/nmSubWxs/nmPebiResultAnimationExporter.cpp index 71a7a8c6..3b257928 100644 --- a/Src/nmNum/nmSubWxs/nmPebiResultAnimationExporter.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiResultAnimationExporter.cpp @@ -255,7 +255,9 @@ nmPebiResultAnimationExporter::Request::Request() m_bScaleGridVisible(false), m_bWellNamesVisible(true), m_bGradientBackground(false), - m_pCamera(nullptr) + m_pCamera(nullptr), + m_eMeshDisplayMode( + nmVTKMeshLayer::DisplayMode_SurfaceWithEdges) { m_dBackground[0] = m_dBackground[1] = m_dBackground[2] = 0.0; m_dBackground2[0] = m_dBackground2[1] = m_dBackground2[2] = 0.0; @@ -291,7 +293,9 @@ nmPebiResultAnimationExporter::exportAnimation( oRequest.m_sPropertyId, oDescriptor) || oDescriptor.m_eTimeType != NM_PebiResultProperty_Dynamic || oDescriptor.m_eAssociation != - NM_PebiResultPropertyAssociation_CellData || + NM_PebiResultPropertyAssociation_CellData || + !nmVTKMeshLayer::isValidDisplayMode( + oRequest.m_eMeshDisplayMode) || !oRequest.m_oExportSettings.isValid(nAvailableFrameCount) || oRequest.m_sTargetFilePath.isEmpty() || oRequest.m_pCamera == nullptr) { @@ -370,8 +374,7 @@ nmPebiResultAnimationExporter::exportAnimation( nmVTKScene oScene(pRenderer); nmVTKMeshLayer* pMeshLayer = new nmVTKMeshLayer( QString::fromLatin1(EXPORT_MESH_LAYER_ID)); - pMeshLayer->setDisplayMode( - nmVTKMeshLayer::DisplayMode_SurfaceWithEdges); + pMeshLayer->setDisplayMode(oRequest.m_eMeshDisplayMode); pMeshLayer->getActor()->GetProperty()->SetEdgeColor(0.0, 0.0, 0.0); pMeshLayer->getActor()->GetProperty()->LightingOff(); if(!pMeshLayer->setInputConnection( diff --git a/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp b/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp index 29ece80f..981e3807 100644 --- a/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp @@ -189,6 +189,8 @@ public: m_pScaleGridLayer(nullptr), m_pWellLayer(nullptr), m_pAdapter(nullptr), + m_eMeshDisplayMode( + nmVTKMeshLayer::DisplayMode_SurfaceWithEdges), m_nCurrentFrameIndex(-1), m_nSnapshotBindingRevision(0), m_nViewportWidth(0), @@ -214,6 +216,18 @@ public: return m_pContainer != nullptr ? m_pContainer->getScene() : nullptr; } + /** @brief 将窗口偏好应用到现有结果网格,不触发渲染。 */ + void applyMeshDisplayModeWithoutRender() + { + if(m_pMeshLayer == nullptr) { + return; + } + m_pMeshLayer->setDisplayMode(m_eMeshDisplayMode); + // Contour 使用黑色单元边线,其余模式关闭边线但保留该颜色偏好。 + m_pMeshLayer->getActor()->GetProperty()->SetEdgeColor( + 0.0, 0.0, 0.0); + } + bool synchronizeLayerPointers() { nmVTKScene* pScene = getScene(); @@ -335,6 +349,7 @@ public: m_pMeshLayer->getActor()->GetProperty()->SetEdgeColor( 0.0, 0.0, 0.0); m_pMeshLayer->getActor()->GetProperty()->LightingOff(); + applyMeshDisplayModeWithoutRender(); } if(m_pScalarBarLayer == nullptr) { @@ -471,11 +486,15 @@ public: } // MeshLayer 在触碰旧 Mapper 前完成全部校验,失败不会破坏旧画面。 - return m_pMeshLayer->setInputConnection( - pAdapter->getOutputPort(), - pAdapter->getCurrentScalarArrayName(), - nmVTKMeshLayer::ScalarAssociation_CellData, - pLookupTable); + if(!m_pMeshLayer->setInputConnection( + pAdapter->getOutputPort(), + pAdapter->getCurrentScalarArrayName(), + nmVTKMeshLayer::ScalarAssociation_CellData, + pLookupTable)) { + return false; + } + applyMeshDisplayModeWithoutRender(); + return true; } void applyScalarBarLayout() @@ -513,9 +532,7 @@ public: { synchronizeLayerPointers(); if(m_pMeshLayer != nullptr) { - // 结果网格固定显示彩色表面和黑色单元边线,不保存可关闭的偏好。 - m_pMeshLayer->setDisplayMode( - nmVTKMeshLayer::DisplayMode_SurfaceWithEdges); + applyMeshDisplayModeWithoutRender(); m_pMeshLayer->setScalarVisibility(bHasData); // 彩色结果网格是有效快照的主内容,不提供独立隐藏状态。 m_pMeshLayer->setVisible(bHasData); @@ -677,6 +694,7 @@ public: QString m_sCurrentPropertyId; /** @brief 按稳定属性 ID 保存的窗口级样式;clear 不删除。 */ QMap m_mapDisplaySettings; + nmVTKMeshLayer::DisplayMode m_eMeshDisplayMode; ///< 本窗口显示偏好。 int m_nCurrentFrameIndex; /** @brief 不同快照对象完整提交成功后的单调序号,clear 和失败均不回退。 */ quint64 m_nSnapshotBindingRevision; @@ -1139,6 +1157,35 @@ bool nmPebiResultSceneController::applyCurrentDisplaySettings( return true; } +void nmPebiResultSceneController::setMeshDisplayMode( + nmVTKMeshLayer::DisplayMode eMode) +{ + Q_ASSERT(isResultSceneGuiThread()); + if(!isResultSceneGuiThread() || m_pPrivate == nullptr || + !nmVTKMeshLayer::isValidDisplayMode(eMode)) { + return; + } + + m_pPrivate->discardActiveDataIfLayersLost(); + if(m_pPrivate->m_eMeshDisplayMode == eMode) { + return; + } + + m_pPrivate->m_eMeshDisplayMode = eMode; + m_pPrivate->applyMeshDisplayModeWithoutRender(); + if(hasSnapshot() && m_pPrivate->m_pContainer != nullptr) { + m_pPrivate->m_pContainer->renderView(); + } +} + +nmVTKMeshLayer::DisplayMode +nmPebiResultSceneController::getMeshDisplayMode() const +{ + return m_pPrivate != nullptr + ? m_pPrivate->m_eMeshDisplayMode + : nmVTKMeshLayer::DisplayMode_SurfaceWithEdges; +} + void nmPebiResultSceneController::setScalarBarVisible(bool bVisible) { Q_ASSERT(isResultSceneGuiThread()); diff --git a/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp index 3dd3dbf5..3a9665b0 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp @@ -3,10 +3,12 @@ #include "nmPebiGridSceneController.h" #include "nmPebiGridViewData.h" +#include "nmVTKMeshLayer.h" #include "nmVTKViewCommandController.h" #include "nmWxVTKRenderContainerWidget.h" #include +#include #include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include #include namespace { @@ -33,6 +36,7 @@ nmWxPebiGridViewWidget::nmWxPebiGridViewWidget(QWidget* pParent) m_pSceneController(nullptr), m_pToolBar(nullptr), m_pBoundsGridAction(nullptr), + m_pDisplayModeCombo(nullptr), m_pGridInfoLabel(nullptr), m_pStatusLabel(nullptr), m_bHasViewData(false) @@ -41,6 +45,7 @@ nmWxPebiGridViewWidget::nmWxPebiGridViewWidget(QWidget* pParent) // 控制器必须在容器之后创建,以便使用当前实例独占的 Scene 和相机。 m_pSceneController = new nmPebiGridSceneController(m_pRenderContainer); + synchronizeDisplayModeFromScene(); resetControls(); setControlsEnabled(false); m_pRenderContainer->showEmptyState(tr("No grid data.")); @@ -176,18 +181,47 @@ void nmWxPebiGridViewWidget::createUi() m_pStatusLabel->hide(); pMainLayout->addWidget(m_pStatusLabel); - // 底栏只承担几何信息展示,不放置属性或渲染模式控件。 + // 显示模式属于当前预览窗口,业务控件不下沉到通用渲染容器。 QWidget* pControlBar = new QWidget(this); QHBoxLayout* pControlLayout = new QHBoxLayout(pControlBar); pControlLayout->setContentsMargins(8, 5, 8, 5); pControlLayout->setSpacing(6); + QLabel* pDisplayLabel = new QLabel(tr("Display"), pControlBar); + pDisplayLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + m_pDisplayModeCombo = new QComboBox(pControlBar); + m_pDisplayModeCombo->addItem( + tr("Point"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_Point))); + m_pDisplayModeCombo->addItem( + tr("Wireframe"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_Wireframe))); + m_pDisplayModeCombo->addItem( + tr("Surface"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_Surface))); + m_pDisplayModeCombo->addItem( + tr("Contour"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_SurfaceWithEdges))); + m_pDisplayModeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_pDisplayModeCombo->setFixedHeight(24); + m_pDisplayModeCombo->setSizePolicy( + QSizePolicy::Preferred, QSizePolicy::Fixed); + m_pGridInfoLabel = new QLabel(pControlBar); m_pGridInfoLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + pControlLayout->addWidget(pDisplayLabel, 0, Qt::AlignVCenter); + pControlLayout->addWidget(m_pDisplayModeCombo); + pControlLayout->addSpacing(2); pControlLayout->addWidget(m_pGridInfoLabel); pControlLayout->addStretch(1); pMainLayout->addWidget(pControlBar); + connect(m_pDisplayModeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onDisplayModeIndexChanged(int))); connect(m_pBoundsGridAction, SIGNAL(toggled(bool)), this, SLOT(onBoundsGridToggled(bool))); connect(m_pRenderContainer, SIGNAL(contextMenuAboutToShow(QMenu*)), @@ -218,6 +252,7 @@ bool nmWxPebiGridViewWidget::setViewData( oViewData.getValidCellCount()))); m_pStatusLabel->hide(); m_bHasViewData = true; + synchronizeDisplayModeFromScene(); setControlsEnabled(true); return true; } @@ -275,6 +310,50 @@ void nmWxPebiGridViewWidget::resetControls() void nmWxPebiGridViewWidget::setControlsEnabled(bool bEnabled) { m_pBoundsGridAction->setEnabled(bEnabled); + m_pDisplayModeCombo->setEnabled(bEnabled); +} + +void nmWxPebiGridViewWidget::synchronizeDisplayModeFromScene() +{ + if(m_pDisplayModeCombo == nullptr || m_pSceneController == nullptr) { + return; + } + const int nMode = static_cast( + m_pSceneController->getMeshDisplayMode()); + for(int nIndex = 0; + nIndex < m_pDisplayModeCombo->count(); ++nIndex) { + if(m_pDisplayModeCombo->itemData(nIndex).toInt() == nMode) { + const bool bBlocked = + m_pDisplayModeCombo->blockSignals(true); + m_pDisplayModeCombo->setCurrentIndex(nIndex); + m_pDisplayModeCombo->blockSignals(bBlocked); + return; + } + } +} + +void nmWxPebiGridViewWidget::onDisplayModeIndexChanged(int nIndex) +{ + if(m_pDisplayModeCombo == nullptr || + !m_pDisplayModeCombo->isEnabled() || + m_pSceneController == nullptr || !m_bHasViewData || + !m_pSceneController->hasViewData() || nIndex < 0 || + nIndex >= m_pDisplayModeCombo->count()) { + return; + } + + bool bConverted = false; + const int nMode = m_pDisplayModeCombo->itemData(nIndex).toInt( + &bConverted); + const nmVTKMeshLayer::DisplayMode eMode = + static_cast( + nMode); + if(!bConverted || !nmVTKMeshLayer::isValidDisplayMode(eMode)) { + synchronizeDisplayModeFromScene(); + return; + } + m_pSceneController->setMeshDisplayMode(eMode); + synchronizeDisplayModeFromScene(); } void nmWxPebiGridViewWidget::onBoundsGridToggled(bool bVisible) diff --git a/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp b/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp index 93bbc9c5..9fa2d4e6 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp @@ -4,6 +4,7 @@ #include "nmPebiResultPlaybackController.h" #include "nmPebiResultPropertyDisplayText.h" #include "nmPebiResultSceneController.h" +#include "nmVTKMeshLayer.h" #include "nmWxPebiResultAnimationSettingsDlg.h" #include "nmWxPebiResultColorScaleSettingsDlg.h" @@ -56,6 +57,7 @@ nmWxPebiResultControlBar::nmWxPebiResultControlBar( : QWidget(pParent), m_pPlaybackController(nullptr), m_pSceneController(pSceneController), + m_pDisplayModeCombo(nullptr), m_pPropertyCombo(nullptr), m_pColorSettingsButton(nullptr), m_pFirstButton(nullptr), @@ -125,6 +127,34 @@ void nmWxPebiResultControlBar::setExportInProgress(bool bInProgress) refreshFromController(); } +void nmWxPebiResultControlBar::onDisplayModeIndexChanged(int nIndex) +{ + if(m_pDisplayModeCombo == nullptr || + !m_pDisplayModeCombo->isEnabled() || + m_pPlaybackController == nullptr || m_pSceneController == nullptr || + m_bExportInProgress || m_pPlaybackController->isPlaying() || + !m_pSceneController->hasSnapshot() || nIndex < 0 || + nIndex >= m_pDisplayModeCombo->count()) { + return; + } + + bool bConverted = false; + const int nMode = m_pDisplayModeCombo->itemData(nIndex).toInt( + &bConverted); + const nmVTKMeshLayer::DisplayMode eMode = + static_cast( + nMode); + if(!bConverted || !nmVTKMeshLayer::isValidDisplayMode(eMode)) { + refreshFromController(); + return; + } + if(eMode == m_pSceneController->getMeshDisplayMode()) { + return; + } + m_pSceneController->setMeshDisplayMode(eMode); + emit operationSucceeded(); +} + void nmWxPebiResultControlBar::onPropertyIndexChanged(int nIndex) { if(m_pPlaybackController == nullptr || m_bExportInProgress || @@ -252,6 +282,19 @@ void nmWxPebiResultControlBar::onExportAnimationTriggered() void nmWxPebiResultControlBar::refreshFromController() { + if(m_pDisplayModeCombo != nullptr && m_pSceneController != nullptr) { + const int nDisplayModeIndex = findItemByData( + m_pDisplayModeCombo, + QVariant(static_cast( + m_pSceneController->getMeshDisplayMode()))); + if(nDisplayModeIndex >= 0) { + const bool bDisplayModeBlocked = + m_pDisplayModeCombo->blockSignals(true); + m_pDisplayModeCombo->setCurrentIndex(nDisplayModeIndex); + m_pDisplayModeCombo->blockSignals(bDisplayModeBlocked); + } + } + // 控件状态严格镜像四类 Scene 状态:无快照、静态、单帧动态、多帧动态。 const bool bAvailable = m_pPlaybackController != nullptr && m_pPlaybackController->isAvailable(); @@ -263,6 +306,7 @@ void nmWxPebiResultControlBar::refreshFromController() m_sDisplayedSnapshotId.clear(); m_nDisplayedBindingRevision = 0; m_listDisplayedPropertyIds.clear(); + m_pDisplayModeCombo->setEnabled(false); m_pPropertyCombo->setEnabled(false); m_pColorSettingsButton->setEnabled(false); m_pFirstButton->setEnabled(false); @@ -336,6 +380,7 @@ void nmWxPebiResultControlBar::refreshFromController() nFrameCount > 1; const bool bPlaying = m_pPlaybackController->isPlaying(); const bool bLocked = bPlaying || m_bExportInProgress; + m_pDisplayModeCombo->setEnabled(!bLocked); m_pPropertyCombo->setEnabled(!bLocked); m_pColorSettingsButton->setEnabled(!bLocked); m_pTimeCombo->setEnabled(bHasTime && !bLocked); @@ -382,6 +427,37 @@ void nmWxPebiResultControlBar::createUi() pLayout->setContentsMargins(4, 3, 4, 3); pLayout->setSpacing(4); + QLabel* pDisplayLabel = new QLabel(tr("Display"), this); + pDisplayLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + m_pDisplayModeCombo = new QComboBox(this); + m_pDisplayModeCombo->addItem( + tr("Point"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_Point))); + m_pDisplayModeCombo->addItem( + tr("Wireframe"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_Wireframe))); + m_pDisplayModeCombo->addItem( + tr("Surface"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_Surface))); + m_pDisplayModeCombo->addItem( + tr("Contour"), + QVariant(static_cast( + nmVTKMeshLayer::DisplayMode_SurfaceWithEdges))); + m_pDisplayModeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_pDisplayModeCombo->setFixedHeight(24); + m_pDisplayModeCombo->setSizePolicy( + QSizePolicy::Preferred, QSizePolicy::Fixed); + const int nInitialDisplayModeIndex = findItemByData( + m_pDisplayModeCombo, + QVariant(static_cast( + m_pSceneController->getMeshDisplayMode()))); + if(nInitialDisplayModeIndex >= 0) { + m_pDisplayModeCombo->setCurrentIndex(nInitialDisplayModeIndex); + } + QLabel* pPropertyLabel = new QLabel(tr("Property"), this); pPropertyLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); @@ -436,6 +512,9 @@ void nmWxPebiResultControlBar::createUi() m_pExportButton->setIconSize(QSize(16, 16)); m_pExportButton->setDefaultAction(m_pExportAction); + pLayout->addWidget(pDisplayLabel, 0, Qt::AlignVCenter); + pLayout->addWidget(m_pDisplayModeCombo); + pLayout->addSpacing(CONTROL_GROUP_GAP); pLayout->addWidget(pPropertyLabel, 0, Qt::AlignVCenter); pLayout->addWidget(m_pPropertyCombo); pLayout->addWidget(m_pColorSettingsButton); @@ -450,6 +529,8 @@ void nmWxPebiResultControlBar::createUi() pLayout->addWidget(m_pExportButton); pLayout->addStretch(1); + connect(m_pDisplayModeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onDisplayModeIndexChanged(int))); connect(m_pPropertyCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onPropertyIndexChanged(int))); connect(m_pColorSettingsButton, SIGNAL(clicked()), diff --git a/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp index 88a3417d..03ba6a54 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp @@ -7,6 +7,7 @@ #include "nmPebiResultPlaybackController.h" #include "nmPebiResultSceneController.h" #include "nmPebiResultSnapshot.h" +#include "nmVTKMeshLayer.h" #include "nmVTKViewCommandController.h" #include "nmWxPebiResultControlBar.h" #include "nmWxPebiResultAnimationExportDlg.h" @@ -300,10 +301,13 @@ void nmWxPebiResultViewWidget::onExportAnimationRequested() m_pSceneController->getCurrentSnapshotId(); const QString sFrozenPropertyId = m_pSceneController->getCurrentPropertyId(); + const nmVTKMeshLayer::DisplayMode eFrozenMeshDisplayMode = + m_pSceneController->getMeshDisplayMode(); const int nFrameCount = pFrozenSnapshot->getPropertyFrameCount( sFrozenPropertyId); if(nFrozenBindingRevision == 0 || sFrozenSnapshotId.isEmpty() || sFrozenPropertyId.isEmpty() || nFrameCount <= 1 || + !nmVTKMeshLayer::isValidDisplayMode(eFrozenMeshDisplayMode) || !m_pSceneController->isPropertyTimeDependent(sFrozenPropertyId)) { return; } @@ -333,7 +337,9 @@ void nmWxPebiResultViewWidget::onExportAnimationRequested() m_pSceneController->getSnapshotBindingRevision() != nFrozenBindingRevision || m_pSceneController->getCurrentSnapshotId() != sFrozenSnapshotId || - m_pSceneController->getCurrentPropertyId() != sFrozenPropertyId) { + m_pSceneController->getCurrentPropertyId() != sFrozenPropertyId || + m_pSceneController->getMeshDisplayMode() != + eFrozenMeshDisplayMode) { QMessageBox::warning( this, tr("Export Animation"), tr("The displayed result changed before export started.")); @@ -354,6 +360,7 @@ void nmWxPebiResultViewWidget::onExportAnimationRequested() oRequest.m_pSnapshot = pFrozenSnapshot; oRequest.m_sPropertyId = sFrozenPropertyId; oRequest.m_oDisplaySettings = oDisplaySettings; + oRequest.m_eMeshDisplayMode = eFrozenMeshDisplayMode; oRequest.m_oExportSettings = oSettingsDialog.getSettings(); oRequest.m_sTargetFilePath = oSettingsDialog.getTargetFilePath(); oRequest.m_bScalarBarVisible = From cf69850bff950146babfc19c7101683ad707f823 Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Thu, 22 Oct 2026 09:51:04 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(nmNum):=20=E7=A7=BB=E9=99=A4=20PEBI=20?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E8=A7=86=E5=9B=BE=E7=9A=84=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除输入修改后显示旧结果的黄色提示栏 - 调整错误提示优先级,过期结果仍正常显示操作错误 - 清理对应中文翻译并重新生成 qm 文件 - 同步更新提示栏相关注释 --- Bin/Config/Lang/cn/nmNum_cn.qm | Bin 158443 -> 158280 bytes Bin/Config/Lang/cn/nmNum_cn.ts | 1 - .../nmNum/nmSubWxs/nmWxPebiResultViewWidget.h | 8 ++++---- .../nmSubWxs/nmWxPebiResultViewWidget.cpp | 15 +++------------ 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 9fbf221573fcae9bbff431cb9bc4c5fdd0b2482e..5ca53d6493831b86278be7aa52713b386b5913d8 100644 GIT binary patch delta 3468 zcmXArdt6l27RT3KGiQc#=EV#m?->}F8J;sJFrWr%DyUben~o$3n&zW>MJq$oRD7kC zPwomcQ>&YlZ!JHFnQuhB6=ESJDi|t~38pE55Abg1%s=1HK4;F}Yp=&|t=o0t*$d*j z9xSlL-^Iq346);1YfB34=r~$ZYGIQ~${U}*xDi0;2duG6=EFQM5tC&a&&f1zmT5>XqPVk#-Dx|&D4&fByAXJf}6 zYR9K6k=hl`V8=axS$=>C!JOTEr?CKY_j4|%bY;Qt(6gXCIRh~6FeuO4fKA&0%G#;G zQfx9iR(OfVX`s9~3)u2FP_`xl+i=NCgflYDVbrWVEw%p%!iFlq$R;Wm+~_xj+61T6 z@f3u8DS$m1$fnAWLdrm>IRltDh6+^{W}($8moXO9syV=HHJ~=Q0d;RswaSbwJE=`& zwssx`_09>vT5f^5(gd*gM=x1SA5d2*fpxekK|S7>3ZWnKeFO8rHti!|50=qpbt;=k zb!rRKQ@h%kr~VZ(N1OmQuT0`Ml)OZBEOm))srw8} zE!hMZ_8g^4PV}Efg_6Cu|4o?n)&*dW$1tntGhor9VRp$KfCUAy}G+C1wYuybsOX`5Fy$9#tZ3LJ%6za}@4CwP7)W0Y3gc%1{q%vTSlc`RViOnl0 zOq+q-^C(~I5HnfmXHDE6pV4aVY^!NE8@zo6KyfF_y0!=4Mls6?*aH~6jJ@>y5YUjAI&J1~9-(TT8TDUMn=XdT`Y>#&qI7)#OCyioF>nmB-hTl4 z??mNbe!!w;6n*pfhJ8_cj33}1g1WQ^z>2P*ei~ngpFqRkM*vhh>^Y35-QONMqBmpH zY--RSl`bs7H-4%GR2r$wP=JqCk>K0kI0SdS!s}=MpSWvpB_K{Gk8h*3bvrhPv;+Il zj?GM%cA->5YFSIH&1I_`o%~a@q&H`^8M_R^qu0R;yu8AX`ijD4cJSq(wEg3fo!ln=T@(HyE{u<#c zxJL};nLk-b8#^D^S4+J_L%A?yC$H<db)YXimr+jPWB zjQEf|!K1BzzAe0;&b9utQZHHPd%~*BDz5B5c!{RDR2^J^evOn6!aEP;huBT6uL;Ly z?&4QGCmetI9I&PYDh=u1D@6FIVhzCTy~59_W?*%Dg}NEFz&2`xOK(O3RKF-(Uep0> zY>{yJ+0|kTNeHztCD}rq&ntcqo=jQ@EXm|0hEElqtmX;W@E;Xioy7(GRTXn^*(`cN z)QkK2@i6U}Hk0IdB^{msQU0mT;eLHADpwNKS2Q3)_?k-BnDFtFArb>%%?!$a%T zrxy0+wSR{4t!@l#rc$dDFMU8&)*MM(?-OEujr(IBg+*rI;|j{>c(|4}M>;0C zdH5!XMFSfFO1=~4Hu3Q)f0(%V7v6$eriiQdGGMm~sLtU=?NZW3JD8JFqV0I8lk%f8 z&~}hEM~}v9+o(O-9{cb|$uuyO%izmiGM!Rp*ImgpVi3TcrCy@)APtFGkE&{Fh{-|U zb(9dBVe+k#=HziJ>ds4Zzv=<#YoZ0Q1ur#pOKU$sKwGf1?qyyiTRhVGjA6jWeJE{w ze2#a9iPF}Jg}euxleX{M1F)i>wEZskQu_gEhk6FEnop!14$kk=WY!WT#Mz}A8>Hi> zWBJ(Wq5QZUscWrN?b^zH>Y(yCyS4sz>0Ij|J_K%*em?bVFx?>49pi^iVNz4+4epU! z)D;)NdXj&9f7Y8k@u|H$8iNoCs9C2mY~vy~?m3O&tOM9@O&Z^c1>Bx$jlc5@un7k> zL6%cIlLpX{c&AC&u5lK%0!FwrNdv#(oz$1Q;+^PIO9=^f>9>zHBTBgL_FP5z30W+j z$`T6j`VtbHsVt7todu=~Co~7X)B_xzt~uCL&lCGB?RL%xep0IGe8TNLQ>p2i$Rqgt zUz+Z@i+HK8q!bsgvHw!OtC$Zk4K6ntR*-+9BZz57{yqWN%b#i|4$9?2Rkn6g%`h%2 z{m7H}k*LvrzV$V3^&M(Yw6Hw#@8x1I(2!oErRxpaQv(ISpr=&UYi+Mrv<)To0KNNa zn=0M{{?pz#*$r@XrnaTvKA!>prEN{;_O>3<-m7>vQ7og$y_ciz8nyN2UAc}Dk}~n; zE-FgOvDRMHeLa%9Zp|#+{tdhZ>~QJ!ABzMwd8F=;wg6c3Pt=^`#;cVSmh6Zy>pIHU z0Lxme>pXFsk8Fc=-S6=@68NN zuc!4d3A`SB1buGSNZ!3i==1bFfE`$`&+oj%_PR=e7r{*Xz&y<_i$?ip-o}^)-L(0d_5nvfY_zxj?1v8qvovbb1b;QNgjJP()E% z(K7!yY70_F?INPK4(ha8wTNwP6%|oYp`ub93$EZEm^*o#!}-pGbKbl6zyET7x*+_~ zDtzq00;)W%>`B#l6Fv^9$~R%qTU8tNtiP(EV{BUtfP5sd-!@A=?{kRQEUBF*sUIO} zs*wzyA{o|3t;~YY3Q3M8@!H?`UrzzMww+?o99RvIyaRC1GRe@X029K1T|OiEyn>cv zF+Q6}eK^2=p*|;zPtZDmMecy%4cvbIrY8VP_XBGWqx=TghivjffD;X6DqTgtcH~$D2(M$OXJ^Pj_6;`(45Q-OhvG7XIELePGPn1guX_ zHOg3Kr>&eMNmr%M8^*NSb^c*!W{GVM!dYCATHpcf*9WkAc1Dc8Gq>Fe!8eu>Y!H zl5HcfjLVYM&m^x*ll<>d$;Vl=Tvg$N5iqSR0l+Ora$GY^EB_E!cRBeB7V#!Q#>dn6 z0>7hl!Rq}D%)l4G9$tnSx%?Z&wea@bXdad&R3qrwVLBpMw71tlW@9wp;ZBFBY$Cg0 z69=*(x2hV@{}RQE798wE`JyRma2YIGd;ysGB`hlX3|P=~D6YB(u-qAzR5Kpb@vyAC z0a)#SB%i*ZCeen!jUl_}#rnz9*%*qD1a(RC0d>hxAIJCd;3yo3P6Q18JAA)00oeVO z&={M}kN7&xaZU;uIsuwjv;y1k5YDdZ0C;}_w4U7pC=7+RH6l-#ci@`16WGgUYIRP+ z-wovNl7IuAl<8s?I+@>Roq*mWsnVs`;68zk`>Ft-^chROu?OH*DNFU*1L&(~Q^&3V zH0P4h)r65YN^#Y*JCyHg!6(jC!?C_er(JcZ8ACm;!J~eOC;`?&?A*H1z`j6s@$vV- z3hP+sC%hQ?tn7v?3)qcW>}GKbuy@PY%^!GiG~Hpp7wLdqXrUCfd3G6b8)zG_|73QNAY61L!)U7g*6XROj*Mz;{sd+5`;uqIPXDUPDTEH;K;Eou-!V0d{E_t#aodSWNZq ze-gGiEvVfF>|#C1JyNk(Pw5^R!VgZzcM+gQK@A=z)Ctt?p+oypvU_BB|4SzDnuG#h znM?X)KzvV9ca!oxOGKx1S?13oKgg5R=Q)bqq?p0$OWQ!UdE#MU9aANLyDIs(SMvE` z$yb9N@-RyddMfE}lN^>JX$+AJ79~TgWSe{Yflb^htNzNLtCicD@p8GEo)Q<@ZPeG>|T1- zM*c&rteH}V#0rhFKkU7{lX_C+km;f}MlP@Z2Y=i|Jwq-9*2!&?$MGteBOmehGM<#> z4sp;F`S?2C1GQ%3wQHqoRJ@U^9-=gpQzGzl-mLMxr6HgiucOT$MTxEIEmVQbr`B5J1@ps^7peC zWOL=Oa!P1t}D#* zd07d9Fo|?js=Cb1R5Iz*{{z|8HS?H2Y;re8^ONy&oc%cpLQnWYl z`g~eQtMoQ(pG-&eR&Tpf`NF{exnJp%;|}oUNrxEZMe=|oboQW>02}&b(5e87Xvk5f z6|Cp2cRd{m(6e4@52$$U;W%aKj`hIyj8uLAlYs53ki6olEPKrz*dKe8W&htt*9qn7 zy*y~aqH^`VMqtk^R1;{z`;3|bQ+yFNDfjl}0}~pR`#!n{u;Dx9H(4o$#UQz@PEB7`;$ zwV+Z*O+&K`y0xmeuWA5l&p2d0jjGJ<^#DuEsx0vmpmqz5A6Ce=QNyrQpNDHy8yRmX zuG3VT-fsaI2CA){&w=%vC4ZyI=We2E*9{#&`6E>w_yAjWT=L2x$~1Zf?o#ddIRS7# zPIaJ!?|)64>QI&^urgoO;cR{*ka^NZ<4o2;eMS@dmXN>6f*!GyVls&#T0wSpC1A)* zT5htw@lx>IdyF6MEJ0Vp6XeQ(5a_)a*oY~Df#0N9Z-y|eSIr0ZSiyL<1K17}tRKD( zXq+p=hQ0+5StpEY91md46vm$56S@5n*-aUxb;7J|@c^m_AzQ%*RUE9_H;=-wn0PA&)Zdnpu+=>VwuPFUKB z0GShovWt8O-eJPJy^OE&x$vf>rPowzYf1)yvT7y&3EtHHQ30k*V;*uGB zEv;w8rC)gP%VRwig=C2xTf_|?A`eglwTE~`+Ql6QO8|P#h+pm71F(9e_|*d*)+cX> zyOagMnm-kHnYrJMki1|aW2i~&iWZNZ4B@@|0i}ngiv1ztY3mNY%^#>f)b!ewa`8-e zBA_KkJb%K@FS47()}s@F&1GWeMjpkxE5$!{WC4VsWKo`Y@6YbMb9_y%VWZe-N(qbg ze&DQ;4+V4yb=G`24%j=dJ8OP2^FFnVYQntORcZ*cXcgm}Ek)gY2%mC}9`g-gKppjk zSx_h-W4KA|9PT{1ig$1?Go^WR>^K5~t;vbz)?IbFQ< zSCp&ws0vgsr>-bIzZZ}(Itgzl zQ+{+RURXp&qILNDd}@!j;q@%?9ByX+q4?oCd@zMFhiAA|tJUjH0W1Ah@@ghE4Y#2m zpWDN;43}rCr^F$JW+pdqvbJr;f6ZDJ(XV)yl7{P z-n&}8;u+7C$64x%vHbwwcBm`gP6T$Vk=kQSc+W&~n+a8s6mIikhiJSl2?GkL($*|& z*G!n7%8$u~=ER!ae$mVt?FB3}(II-Dr<&Mgx80gDod|5DP4e1k>Wi&Ft1B%ZVZn$n zsvj}ks-LZSy7)AJ>?2M8aQ;GTt!5z24Or|T&A{B*0Poo~18Wla)UorZM}A!%6?ZTy zj%{kmw9HJKnzDi3n3MVFPxt1;4Y<6QlMysGVd-nBVk*2Bm_2A}?fkK8Zx*jCY00gQ zKo#&G1^*qLShR5AoPxyx^9mLeEnXCmH@kRFKu+H5g4{XpS_0DY3YW|)$lbKS$UHac NH5h#GXBRBZ{2v(^c@zKu diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index aae1c227..4f9c377a 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -2989,7 +2989,6 @@ Reason: %1 Well Names井名 Unable to display the latest result.无法显示最新结果。 Unable to display the latest result: %1无法显示最新结果:%1 - Current inputs have changed. Showing the last successful result.当前输入已修改,正在显示上一次成功求解的结果。 Export Animation导出动画 Another result animation export is already in progress.已有结果动画正在导出。 Unable to read the result animation timeline.无法读取结果动画时间轴。 diff --git a/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h b/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h index c4fe2585..1feeebb1 100644 --- a/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h +++ b/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h @@ -58,9 +58,9 @@ private slots: void onDataManagerDestroyed(QObject* pObject); /** @brief 将业务显隐 QAction 追加到通用右键菜单。 */ void appendContextMenuActions(QMenu* pMenu); - /** @brief 转发非阻塞操作错误,但不覆盖绑定失败或过期提示。 */ + /** @brief 转发非阻塞操作错误,但不覆盖绑定失败提示。 */ void onControlOperationFailed(const QString& sError); - /** @brief 明确操作成功后清除旧普通错误,不影响绑定失败或过期状态。 */ + /** @brief 明确操作成功后清除旧普通错误,不影响绑定失败状态。 */ void onControlOperationSucceeded(); /** @brief 将 QVTK 视口尺寸同步给结果场景,不主动触发额外渲染。 */ void onViewportSizeChanged(int nWidth, int nHeight); @@ -90,7 +90,7 @@ private: bool bCurrent); /** @brief 从 SceneController 镜像三个业务 QAction 的勾选和可用状态。 */ void synchronizeBusinessActions(); - /** @brief 根据“绑定失败、过期、操作错误”的固定优先级刷新提示栏。 */ + /** @brief 按绑定失败、操作错误的优先级刷新提示栏,无错误时隐藏。 */ void refreshStatusBar(); /** @brief 断开当前 Manager 的两个连接,不访问已经析构的对象。 */ void disconnectDataManager(); @@ -100,7 +100,7 @@ private: nmPebiResultSceneController* m_pSceneController; ///< 唯一结果场景控制器。 nmWxPebiResultControlBar* m_pControlBar; ///< 独占回放控制器和 Timer 的底栏。 QToolBar* m_pToolBar; ///< Qt 父对象拥有的右侧竖向工具栏。 - QLabel* m_pStatusLabel; ///< 过期或错误的非阻塞提示栏。 + QLabel* m_pStatusLabel; ///< 绑定失败或操作错误的非阻塞提示栏。 QAction* m_pScalarBarAction; ///< 色标显隐动作。 QAction* m_pScaleGridAction; ///< 比例网格显隐动作。 diff --git a/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp index 03ba6a54..0c0d15a0 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp @@ -238,9 +238,8 @@ void nmWxPebiResultViewWidget::appendContextMenuActions(QMenu* pMenu) void nmWxPebiResultViewWidget::onControlOperationFailed( const QString& sError) { - // 高优先级状态存在时丢弃普通错误,避免其在过期提示解除后突然出现。 - if(!m_sBindingError.isEmpty() || - (m_bObservedStateValid && !m_bObservedSnapshotCurrent)) { + // 绑定失败优先显示;输入修改不再提示,也不屏蔽后续真实操作错误。 + if(!m_sBindingError.isEmpty()) { return; } m_sOperationError = sError; @@ -252,7 +251,7 @@ void nmWxPebiResultViewWidget::onControlOperationSucceeded() if(m_sOperationError.isEmpty()) { return; } - // 这里只清除最低优先级的普通操作错误;刷新函数仍优先显示绑定失败和过期。 + // 这里只清除普通操作错误;刷新函数仍优先显示绑定失败。 m_sOperationError.clear(); refreshStatusBar(); } @@ -720,14 +719,6 @@ void nmWxPebiResultViewWidget::refreshStatusBar() m_pStatusLabel->show(); return; } - if(m_bObservedStateValid && !m_bObservedSnapshotCurrent) { - m_pStatusLabel->setStyleSheet( - "QLabel { color: #6b5200; background: #fff4bf; } "); - m_pStatusLabel->setText(tr( - "Current inputs have changed. Showing the last successful result.")); - m_pStatusLabel->show(); - return; - } if(!m_sOperationError.isEmpty()) { m_pStatusLabel->setStyleSheet( "QLabel { color: #a32626; background: #fdecec; } ");