From 16c7387468f6e375c99db303d5720f97393fd239 Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Tue, 27 Oct 2026 11:07:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=96=87=E5=AD=97=E8=A3=81=E5=88=87=E5=92=8C=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E6=AE=8B=E7=95=99=EF=BC=8C=E5=AE=8C=E5=96=84=E7=BD=91=E6=A0=BC?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复时间变表皮系数、射孔关闭工具栏文字显示不全 - 调整 DFN 导入、井与储层编辑、井储计算及 PEBI 控件尺寸,适配不同字体 - 修复隐藏对话框在 Windows 任务栏预览中的残留 - 网格失败接入框架日志,增加井半径、边界和网格尺度检查 - 向网格及求解窗口传递简短失败原因,取消操作不记录失败 - 更新中文 TS/QM 和翻译提取标记,统一相关文件为 CRLF --- Bin/Config/Lang/cn/nmNum_cn.qm | Bin 191037 -> 194932 bytes Bin/Config/Lang/cn/nmNum_cn.ts | 26 +++++ .../nmCalculation/nmCalculationPebiGrid.h | 4 + .../nmCalculation/nmCalculationPebiGridTask.h | 2 + Include/nmNum/nmSubWnd/nmSubWndGrid.h | 2 +- .../nmCalculationDllPebiSolverTask.cpp | 6 +- .../nmCalculation/nmCalculationPebiGrid.cpp | 90 ++++++++++++++---- .../nmCalculationPebiGridTask.cpp | 15 ++- Src/nmNum/nmSubWnd/nmSubWndGrid.cpp | 10 +- Src/nmNum/nmSubWnd/nmSubWndMain.cpp | 3 + Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp | 2 + .../nmSubWxs/nmWxAutomaticFittingStart.cpp | 2 + Src/nmNum/nmSubWxs/nmWxDFNLoadFromFile.cpp | 6 +- Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp | 3 +- Src/nmNum/nmSubWxs/nmWxForecast.cpp | 2 + Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp | 2 +- .../nmSubWxs/nmWxPebiResultControlBar.cpp | 6 +- Src/nmNum/nmSubWxs/nmWxPerforationClosing.cpp | 12 ++- .../nmWxPostprocessingAnimationWidget.cpp | 2 + .../nmWxReservoirPropertiesEditor.cpp | 2 +- Src/nmNum/nmSubWxs/nmWxSensitive.cpp | 6 ++ Src/nmNum/nmSubWxs/nmWxTimeDependentSkin.cpp | 30 ++++-- Src/nmNum/nmSubWxs/nmWxWellEditor.cpp | 2 +- .../nmWxWellboreStorageCalculator.cpp | 4 +- ...mWxWellboreStorageCalculatorTubingData.cpp | 4 +- .../nmWxWellboreStorageCalculatorVolume.cpp | 4 +- 26 files changed, 191 insertions(+), 56 deletions(-) diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 3f51c91bd9995907e1dc1cae355b301d017dfb94..c685584d5d507dd6e27d4afeab83fb5040c2e0d5 100644 GIT binary patch delta 19601 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 delta 15822 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 E06VA4*#H0l diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index f776ef75..9cd4a640 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -8902,4 +8902,30 @@ Average pressure in contour: %2 MPa 模型已发生变化,请重新生成预测。 + + nmPebiGridDiagnostics + Only two-dimensional grid input is supported.当前仅支持二维网格输入。 + Grid spacing must be finite and greater than zero (current value: %1).网格尺度必须为有限正数,当前值:%1。 + The boundary must contain at least three edges.工区边界至少需要三条边。 + Boundary edge %1 has missing or non-finite coordinates.边界第 %1 条边的坐标缺失或不是有限数值。 + Boundary edge %1 has zero length. Check coincident points and coordinate rounding.边界第 %1 条边长度为零,请检查重合点及坐标取整造成的重合。 + Vertical well %1 has missing or non-finite coordinates/radius.第 %1 口直井的坐标或井半径缺失,或不是有限数值。 + Vertical well %1 has invalid radius %2 m; it must be greater than zero.第 %1 口直井的半径 %2 m 无效,井半径必须大于零。 + Vertical well %1: radius %2 m is too small to represent at coordinates (%3, %4) m.第 %1 口直井的半径 %2 m 相对于坐标(%3,%4)m 过小,已超出浮点数的可分辨精度。 + Grid input capture/preparation failed. Check the boundary and participating wells.网格输入读取或准备失败,请检查工区边界及参与计算的井。 + Unable to load HX_NWTM.dll (Windows error %1). Check the DLL and its runtime dependencies.无法加载 HX_NWTM.dll(Windows 错误码 %1),请检查网格库及其运行库依赖。 + HX_NWTM_GRID is missing from the DLL (Windows error %1). Check the library version.网格库缺少 HX_NWTM_GRID 入口(Windows 错误码 %1),请检查库版本。 + The grid algorithm encountered an access violation (0xC0000005).网格算法内部发生内存访问异常(0xC0000005)。 + The grid algorithm returned empty grid data. Check the license and geometry inputs.网格算法返回了空网格,请检查授权文件及几何输入。 + The generated grid cannot be displayed: invalid points, cell indices or degenerate cells.生成的网格无法显示,可能存在无效节点、单元索引错误或退化单元。 + Grid calculation raised an exception: %1网格计算发生异常:%1 + Grid calculation raised an unknown exception.网格计算发生未知异常。 + Unable to capture the grid boundary. Check that the analysis has a boundary.无法读取工区边界,请确认当前分析已设置边界。 + Unable to capture well geometry. Check participating well types and fracture endpoints.无法读取井几何信息,请检查参与计算的井类型及裂缝端点。 + Unable to capture fault/fracture geometry.无法读取断层或裂缝几何信息。 + Participating wells do not match the grid well list. Check the primary well and included wells.参与计算的井与网格井列表不匹配,请检查主井及包含井设置。 + The grid result was discarded because the analysis inputs changed. Generate the grid again.划分期间分析输入已改变,本次网格未提交,请重新划分网格。 + Grid generation failed: %1网格划分失败:%1 + Check whether the well radius is too small, and check grid spacing and geometry positions.请检查井半径是否过小、网格尺度及几何位置是否合适。 + diff --git a/Include/nmNum/nmCalculation/nmCalculationPebiGrid.h b/Include/nmNum/nmCalculation/nmCalculationPebiGrid.h index 34dad3f4..e479cd4e 100644 --- a/Include/nmNum/nmCalculation/nmCalculationPebiGrid.h +++ b/Include/nmNum/nmCalculation/nmCalculationPebiGrid.h @@ -103,6 +103,7 @@ struct nmPebiGridInputSnapshot bool m_bCaptured; ///< DataManager 值是否已在所属线程完整捕获。 bool m_bRequireSolverInput; ///< 是否还需组装产量、PVT 等求解输入。 bool m_bValid; ///< 后台场景准备是否完成,可否提交给网格 DLL。 + QString m_sCaptureFailure; ///< 输入捕获失败的具体步骤。 }; /** @@ -121,6 +122,7 @@ struct nmPebiGridResult HX_NWTM_GRID_OUTPUT2 m_oGridOutput2; ///< 网格 DLL 辅助输出。 vtkSmartPointer m_pUnstructuredGrid; ///< 局部构造的 VTK 网格。 bool m_bSucceeded; ///< DLL 和 VTK 转换是否全部成功。 + QString m_sFailureReason; ///< 可直接显示的失败原因及排查建议。 }; class NMCALCULATION_EXPORT nmCalculationPebiGrid @@ -155,6 +157,8 @@ public: nmPebiGridResult& oResult, bool bCreateUnstructuredGrid = true, const QAtomicInt* pCancelRequested = NULL); + /** @brief 向框架日志写入简短失败原因,不修改模型参数或已提交网格。 */ + void recordSnapshotFailure(nmPebiGridResult& oResult, const QString& reason); /** @brief 在主线程校验输入版本,并一次性提交井顺序、网格和单例缓存。 */ bool commitSnapshotResult(nmDataAnalyzeManager* pDataManager, const nmPebiGridInputSnapshot& oSnapshot, diff --git a/Include/nmNum/nmCalculation/nmCalculationPebiGridTask.h b/Include/nmNum/nmCalculation/nmCalculationPebiGridTask.h index 3dc3aba4..141d6ebc 100644 --- a/Include/nmNum/nmCalculation/nmCalculationPebiGridTask.h +++ b/Include/nmNum/nmCalculation/nmCalculationPebiGridTask.h @@ -20,6 +20,8 @@ public: ~nmCalculationPebiGridTask(); /** @brief 在主线程按版本提交后台局部结果;过期结果返回 false。 */ bool commitResult(nmDataAnalyzeManager* pDataManager); + /** @brief 返回已翻译的失败原因,供主线程在任务结束后显示。 */ + QString failureMessage() const; signals: /** @brief 无论成功或失败均通知主线程结束本轮网格任务。 */ diff --git a/Include/nmNum/nmSubWnd/nmSubWndGrid.h b/Include/nmNum/nmSubWnd/nmSubWndGrid.h index 449b1545..ca213328 100644 --- a/Include/nmNum/nmSubWnd/nmSubWndGrid.h +++ b/Include/nmNum/nmSubWnd/nmSubWndGrid.h @@ -64,7 +64,7 @@ class NM_SUB_WND_EXPORT nmSubWndGrid : public iSubWndBaseFit { /** @brief 从 DataManager 构建最新 ViewData 并刷新稳定的网格视图。 */ void showGridResult(); /** @brief 网格失败时恢复旧网格;没有旧网格则显示明确失败提示。 */ - void showGridFailure(); + void showGridFailure(const QString& reason = QString()); /** @brief 清除当前 ViewData,防止切换分析后继续显示旧分析网格。 */ void clearGridResultView(); /** @brief 从防抖开始登记建网活动,使同一分析的求解等待最终提交。 */ diff --git a/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp b/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp index 8d8531bb..f5ac9617 100644 --- a/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationDllPebiSolverTask.cpp @@ -2007,9 +2007,9 @@ bool nmCalculationDllPebiSolverTask::execPebiMode() oGridResult, bCreateUnstructuredGrid, pCancelRequested)) { - return isCancelRequested() - ? false - : fail(tr("Grid generation failed.")); + QString message = tr("Grid generation failed."); + if(!oGridResult.m_sFailureReason.isEmpty()) message += "\n" + oGridResult.m_sFailureReason; + return isCancelRequested() ? false : fail(message); } if(isCancelRequested()) { diff --git a/Src/nmNum/nmCalculation/nmCalculationPebiGrid.cpp b/Src/nmNum/nmCalculation/nmCalculationPebiGrid.cpp index 8eae36a1..2171d3d3 100644 --- a/Src/nmNum/nmCalculation/nmCalculationPebiGrid.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationPebiGrid.cpp @@ -12,6 +12,7 @@ #include #include "nmCalculationUtils.h" +#include "nmPebiGridDiagnostics.h" #include "zxLogInstance.h" #include "nmDataAnalyzeManager.h" @@ -1455,16 +1456,23 @@ bool nmCalculationPebiGrid::captureInputSnapshot( static_cast(vecEffectiveWells[nIndex].m_eMode)); } - // 第三步:把 Map 中的边界、有效井、断层和手工裂缝全部转成 DLL 值类型。 - if(!meshGenPebiBoundary(pDataManager, oSnapshot.m_oGridInput) || - !meshGenPebiWells(pDataManager, + // 第三步:分别记录输入捕获失败的步骤,避免界面只得到一个 false。 + if(!meshGenPebiBoundary(pDataManager, oSnapshot.m_oGridInput)) { + oSnapshot.m_sCaptureFailure = nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Unable to capture the grid boundary. Check that the analysis has a boundary.")); + return false; + } + if(!meshGenPebiWells(pDataManager, oSnapshot.m_oGridInput, oSnapshot.m_vecSolverWellOrder, - setEffectiveWellCodes) || - !meshGenPebiFault(pDataManager, oSnapshot.m_oGridInput) || + setEffectiveWellCodes)) { + oSnapshot.m_sCaptureFailure = nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Unable to capture well geometry. Check participating well types and fracture endpoints.")); + return false; + } + if(!meshGenPebiFault(pDataManager, oSnapshot.m_oGridInput) || !meshGenPebiCrack(pDataManager, oSnapshot.m_oGridInput, oSnapshot.m_vecSolverWellOrder)) { + oSnapshot.m_sCaptureFailure = nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Unable to capture fault/fracture geometry.")); return false; } @@ -1499,6 +1507,7 @@ bool nmCalculationPebiGrid::captureInputSnapshot( setOrderedWellCodes == setEffectiveWellCodes; if(!bSolverOrderValid) { qWarning() << "PEBI solver order does not match effective wells."; + oSnapshot.m_sCaptureFailure = nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Participating wells do not match the grid well list. Check the primary well and included wells.")); return false; } @@ -1822,20 +1831,42 @@ bool nmCalculationPebiGrid::buildPebiScene( return oSnapshot.m_bValid; } +void nmCalculationPebiGrid::recordSnapshotFailure( + nmPebiGridResult& oResult, + const QString& reason) +{ + oResult.m_bSucceeded = false; + oResult.m_sFailureReason = reason; + // 使用框架日志接口,由框架处理跨线程显示及保存;每次失败只写一条简短提示。 + zxLogInstance::getInstance()->writeLogW( + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Grid generation failed: %1")).arg(reason.simplified())); +} + bool nmCalculationPebiGrid::calculateSnapshot( const nmPebiGridInputSnapshot& oSnapshot, nmPebiGridResult& oResult, bool bCreateUnstructuredGrid, const QAtomicInt* pCancelRequested) { + const nmPebiGridResult oEmptyResult; + oResult = oEmptyResult; nmInterruptibleMutexLocker oGridLocker; if(!oGridLocker.lock(&s_oPebiGridMutex, pCancelRequested)) { return false; } - const nmPebiGridResult oEmptyResult; - oResult = oEmptyResult; - if(!oSnapshot.m_bValid || isCancellationRequested(pCancelRequested)) { + if(isCancellationRequested(pCancelRequested)) { + return false; + } + if(!oSnapshot.m_bValid) { + recordSnapshotFailure(oResult, oSnapshot.m_sCaptureFailure.isEmpty() + ? nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Grid input capture/preparation failed. Check the boundary and participating wells.")) + : oSnapshot.m_sCaptureFailure); + return false; + } + const QString inputError = nmPebiGridDiagnostics::validate(oSnapshot.m_oGridInput); + if(!inputError.isEmpty()) { + recordSnapshotFailure(oResult, inputError); return false; } @@ -1847,8 +1878,9 @@ bool nmCalculationPebiGrid::calculateSnapshot( } HMODULE hGridModule = LoadLibrary(L"HX_NWTM.dll"); if(hGridModule == nullptr) { - qWarning() << "Failed to load HX_NWTM.dll. Error code:" - << GetLastError(); + const DWORD error = GetLastError(); + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Unable to load HX_NWTM.dll (Windows error %1). Check the DLL and its runtime dependencies.")).arg(error)); return false; } @@ -1856,8 +1888,9 @@ bool nmCalculationPebiGrid::calculateSnapshot( reinterpret_cast( GetProcAddress(hGridModule, "HX_NWTM_GRID")); if(pfnGenerateGrid == nullptr) { - qWarning() << "Failed to resolve HX_NWTM grid functions. Error code:" - << GetLastError(); + const DWORD error = GetLastError(); + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "HX_NWTM_GRID is missing from the DLL (Windows error %1). Check the library version.")).arg(error)); FreeLibrary(hGridModule); return false; } @@ -1871,6 +1904,11 @@ bool nmCalculationPebiGrid::calculateSnapshot( // 第二步:DLL 输出先落在局部结果,失败时不清空单例缓存和已有成果。 if(!invokePebiGridDllGuarded(pfnGenerateGrid, oSnapshot, oResult)) { // 本轮结果不再用于显示或求解,沿用现有失败通知保留旧成果。 + // 用户取消不是输入失败,不生成误导性的“半径过小”等排查提示。 + if(!isCancellationRequested(pCancelRequested)) + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "The grid algorithm encountered an access violation (0xC0000005).")) + + "\n" + nmPebiGridDiagnostics::failureHint()); nmCalculationUtils::cleanupPebiGridDebugFiles(); FreeLibrary(hGridModule); hGridModule = nullptr; @@ -1888,6 +1926,16 @@ bool nmCalculationPebiGrid::calculateSnapshot( return false; } + if(oResult.m_oGridOutput1.PEBI_cell.p.empty() || + oResult.m_oGridOutput1.PEBI_cell.pindex.empty() || + oResult.m_oGridOutput2.Area.empty()) { + // 自动拟合跳过 VTK 转换时也必须检查空输出,不能把空网格当成功。 + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "The grid algorithm returned empty grid data. Check the license and geometry inputs.")) + + "\n" + nmPebiGridDiagnostics::failureHint()); + return false; + } + // 自动拟合只需要 DLL 数组,可跳过 VTK 构造;网格任务必须生成完整 VTK。 if(bCreateUnstructuredGrid) { oResult.m_pUnstructuredGrid = @@ -1896,6 +1944,10 @@ bool nmCalculationPebiGrid::calculateSnapshot( pCancelRequested); if(oResult.m_pUnstructuredGrid == nullptr || oResult.m_pUnstructuredGrid->GetNumberOfCells() <= 0) { + if(!isCancellationRequested(pCancelRequested)) + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "The generated grid cannot be displayed: invalid points, cell indices or degenerate cells.")) + + "\n" + nmPebiGridDiagnostics::failureHint()); return false; } } @@ -1903,18 +1955,20 @@ bool nmCalculationPebiGrid::calculateSnapshot( oResult.m_bSucceeded = !isCancellationRequested(pCancelRequested); } catch(const std::exception& e) { nmCalculationUtils::cleanupPebiGridDebugFiles(); - zxLogInstance::getInstance()->writeLogF( - QString("C++ Exception: %1").arg(e.what())); - logInputParameters(oSnapshot.m_oGridInput); + if(!isCancellationRequested(pCancelRequested)) + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Grid calculation raised an exception: %1")).arg(QString::fromLocal8Bit(e.what())) + + "\n" + nmPebiGridDiagnostics::failureHint()); if(hGridModule != nullptr) { FreeLibrary(hGridModule); } return false; } catch(...) { nmCalculationUtils::cleanupPebiGridDebugFiles(); - zxLogInstance::getInstance()->writeLogF( - "SEH Exception Occurred"); - logInputParameters(oSnapshot.m_oGridInput); + if(!isCancellationRequested(pCancelRequested)) + recordSnapshotFailure(oResult, + nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Grid calculation raised an unknown exception.")) + + "\n" + nmPebiGridDiagnostics::failureHint()); if(hGridModule != nullptr) { FreeLibrary(hGridModule); } diff --git a/Src/nmNum/nmCalculation/nmCalculationPebiGridTask.cpp b/Src/nmNum/nmCalculation/nmCalculationPebiGridTask.cpp index a6b1d9bd..26281504 100644 --- a/Src/nmNum/nmCalculation/nmCalculationPebiGridTask.cpp +++ b/Src/nmNum/nmCalculation/nmCalculationPebiGridTask.cpp @@ -1,6 +1,7 @@ #include "nmCalculationPebiGridTask.h" #include "nmCalculationPebiGrid.h" +#include "nmPebiGridDiagnostics.h" #include "nmDataAnalyzeManager.h" nmCalculationPebiGridTask::nmCalculationPebiGridTask( @@ -35,8 +36,8 @@ nmCalculationPebiGridTask::~nmCalculationPebiGridTask() void nmCalculationPebiGridTask::run() { // 第二步:后台只消费不可变快照,所有 DLL 输出和 VTK 数据先保存在任务内部。 - const bool success = m_bSnapshotValid && - nmCalculationPebiGrid::getInstance()->calculateSnapshot( + // 无效快照也交给统一入口记录捕获失败原因。 + const bool success = nmCalculationPebiGrid::getInstance()->calculateSnapshot( m_oInputSnapshot, m_oResult); // 完成通知可能引起成果窗口销毁,发信号前先解除 DataManager 使用权。 releaseDataManagerUse(); @@ -54,8 +55,16 @@ bool nmCalculationPebiGridTask::commitResult( return false; } - return nmCalculationPebiGrid::getInstance()->commitSnapshotResult( + const bool committed = nmCalculationPebiGrid::getInstance()->commitSnapshotResult( pDataManager, m_oInputSnapshot, m_oResult); + if(!committed) + m_oResult.m_sFailureReason = nmPebiGridDiagnostics::text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "The grid result was discarded because the analysis inputs changed. Generate the grid again.")); + return committed; +} + +QString nmCalculationPebiGridTask::failureMessage() const +{ + return m_oResult.m_sFailureReason; } void nmCalculationPebiGridTask::releaseDataManagerUse() diff --git a/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp b/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp index facaadc8..897424e8 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp @@ -363,7 +363,7 @@ void nmSubWndGrid::onPebiGridGenerated(bool success) if(success) { showGridResult(); } else if(!hasPendingGridUpdate()) { - showGridFailure(); + showGridFailure(pCompletedTask->failureMessage()); } // 连续变化尚未完成时保持活动状态;求解只能在最后一次提交之后继续。 @@ -442,7 +442,7 @@ void nmSubWndGrid::clearGridResultView() m_pGridView->clearView(); } -void nmSubWndGrid::showGridFailure() +void nmSubWndGrid::showGridFailure(const QString& reason) { if(m_pMainLayout == nullptr || m_pGridView == nullptr) { return; @@ -453,9 +453,11 @@ void nmSubWndGrid::showGridFailure() m_pMainLayout->setCurrentWidget(m_pGridView); if(m_pGridView->hasViewData()) { m_pGridView->showFailure(tr( - "Grid generation failed. Current view is the last successful grid.")); + "Grid generation failed. Current view is the last successful grid.") + + (reason.isEmpty() ? QString() : "\n" + reason)); } else { - m_pGridView->showFailure(tr("Grid generation failed.")); + m_pGridView->showFailure(tr("Grid generation failed.") + + (reason.isEmpty() ? QString() : "\n" + reason)); } } diff --git a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp index 5b23399f..87cbfd21 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp @@ -87,6 +87,7 @@ #include "nmWxNumericalDesign.h" #include "nmWxSensitive.h" #include "nmWxForecast.h" +#include "nmDialogPreviewGuard.h" #include "nmWxReservoirProperties.h" @@ -1875,6 +1876,7 @@ void nmSubWndMain::showSolverProgress() // 某些系统下,对话框右上角的关闭按钮可能仍存 // 使用 WindowFlags 彻底禁用关闭按钮 m_pProgressDlg->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint); + new nmDialogPreviewGuard(m_pProgressDlg); m_pProgressDlg->setMinimumDuration(0); m_pProgressDlg->setAutoClose(false); m_pProgressDlg->setAutoReset(false); @@ -1981,6 +1983,7 @@ QDialog* nmSubWndMain::createResultDialog(const QString& name, const QString& ti dialog->setObjectName(name); dialog->setWindowTitle(title); dialog->setAttribute(Qt::WA_DeleteOnClose, false); + new nmDialogPreviewGuard(dialog); dialog->resize(900, 650); QVBoxLayout* layout = new QVBoxLayout(dialog); layout->setContentsMargins(0, 0, 0, 0); diff --git a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp index f8fd803d..9da2e59e 100644 --- a/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp +++ b/Src/nmNum/nmSubWxs/nmWxAutomaticFitting.cpp @@ -1,5 +1,6 @@ #include "nmWxAutomaticFitting.h" #include "nmCalculationAutoFitPSO.h" +#include "nmDialogPreviewGuard.h" #include "nmCalculationAutoFitLM.h" #include "nmWxAutomaticfittingStart.h" #include "nmWxParameterProperty.h" @@ -318,6 +319,7 @@ nmWxAutomaticFitting::nmWxAutomaticFitting(QWidget *parent, nmSensitivityFitSett setupUI(); setWindowTitle(tr("Automatic fitting")); + new nmDialogPreviewGuard(this); setModal(true); // 恢复旧版默认尺寸,多井参数在右侧树表中滚动查看。 resize(sizeHint()); diff --git a/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp b/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp index 3624112c..fdc4dc36 100644 --- a/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp +++ b/Src/nmNum/nmSubWxs/nmWxAutomaticFittingStart.cpp @@ -1,5 +1,6 @@ #include "nmWxAutomaticfittingStart.h" #include +#include "nmDialogPreviewGuard.h" #include #include #include @@ -398,6 +399,7 @@ nmWxAutomaticfittingStart::nmWxAutomaticfittingStart(QWidget *parent) // 设置窗口属性 setWindowTitle(tr("Auto Fitting Progress")); + new nmDialogPreviewGuard(this); setMinimumSize(1000, 650); setModal(false); } diff --git a/Src/nmNum/nmSubWxs/nmWxDFNLoadFromFile.cpp b/Src/nmNum/nmSubWxs/nmWxDFNLoadFromFile.cpp index 7976c740..1e2be44a 100644 --- a/Src/nmNum/nmSubWxs/nmWxDFNLoadFromFile.cpp +++ b/Src/nmNum/nmSubWxs/nmWxDFNLoadFromFile.cpp @@ -68,7 +68,7 @@ void nmWxDFNLoadFromFile::initUI() // 1. 数据源部分 m_pSourceGroup = new QGroupBox(tr("Data Source"), this); - m_pSourceGroup->setFixedSize(337, 106); + m_pSourceGroup->setMinimumWidth(337); // 使用垂直布局作为主布局(包含按钮行和文件路径行) QVBoxLayout* pSourceMainLayout = new QVBoxLayout(m_pSourceGroup); @@ -128,7 +128,7 @@ void nmWxDFNLoadFromFile::initUI() // 2. 分隔符部分 m_pSeparatorGroup = new QGroupBox(tr("Separators"), this); - m_pSeparatorGroup->setFixedSize(233,106); // 固定大小 + m_pSeparatorGroup->setMinimumWidth(233); // 使用复选框代替单选按钮 m_pSpaceCheck = new QCheckBox(tr("Space"), this); @@ -157,7 +157,7 @@ void nmWxDFNLoadFromFile::initUI() // 3. 信息提示 - 现在放在GroupBox中 m_pInfoGroup = new QGroupBox(tr("Info"), this); - m_pInfoGroup->setFixedSize(255,106); // 固定大小 + m_pInfoGroup->setMinimumWidth(255); m_pInfoLabel = new QLabel( tr("You need to assign at least 4 required types: X1, Y1, X2, Y2."), this); diff --git a/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp b/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp index 6adf2a5c..44eeddd7 100644 --- a/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp +++ b/Src/nmNum/nmSubWxs/nmWxEditWellPlot.cpp @@ -313,7 +313,8 @@ QWidget* nmWxEditWellPlot::createRightPanel() QWidget* nmWxEditWellPlot::createBottomPanel() { m_pOverallBottomPanel = new QWidget(this); - m_pOverallBottomPanel->setFixedHeight(80); // 增加高度以容纳两行内容 + m_pOverallBottomPanel->setMinimumHeight(80); + m_pOverallBottomPanel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); QVBoxLayout* mainBottomVLayout = new QVBoxLayout(m_pOverallBottomPanel); mainBottomVLayout->setContentsMargins(5, 5, 5, 5); diff --git a/Src/nmNum/nmSubWxs/nmWxForecast.cpp b/Src/nmNum/nmSubWxs/nmWxForecast.cpp index 9414e893..fa63a9f1 100644 --- a/Src/nmNum/nmSubWxs/nmWxForecast.cpp +++ b/Src/nmNum/nmSubWxs/nmWxForecast.cpp @@ -1,5 +1,6 @@ #include "nmWxForecast.h" #include +#include "nmDialogPreviewGuard.h" #include #include #include @@ -40,6 +41,7 @@ nmWxForecast::nmWxForecast(QWidget *parent, nmDataAnalyzeManager* manager) setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // 关闭时只隐藏,所属设计面板复用同一个输入窗口。 setAttribute(Qt::WA_DeleteOnClose, false); + new nmDialogPreviewGuard(this); PressureRow tempDefaults; m_currentDurationUnit = tempDefaults.duration.getUnit(); diff --git a/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp index b280df14..de9300b8 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp @@ -209,7 +209,7 @@ void nmWxPebiGridViewWidget::createUi() QVariant(static_cast( nmVTKMeshLayer::DisplayMode_SurfaceWithEdges))); m_pDisplayModeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); - m_pDisplayModeCombo->setFixedHeight(24); + m_pDisplayModeCombo->setMinimumHeight(24); m_pDisplayModeCombo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed); diff --git a/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp b/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp index ebba185a..9005ed70 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiResultControlBar.cpp @@ -467,7 +467,7 @@ void nmWxPebiResultControlBar::createUi() QVariant(static_cast( nmVTKMeshLayer::DisplayMode_SurfaceWithEdges))); m_pDisplayModeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); - m_pDisplayModeCombo->setFixedHeight(24); + m_pDisplayModeCombo->setMinimumHeight(24); m_pDisplayModeCombo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed); const int nInitialDisplayModeIndex = findItemByData( @@ -484,7 +484,7 @@ void nmWxPebiResultControlBar::createUi() m_pPropertyCombo = new QComboBox(this); m_pPropertyCombo->setMinimumWidth(PROPERTY_COMBO_MINIMUM_WIDTH); m_pPropertyCombo->setMaximumWidth(PROPERTY_COMBO_MAXIMUM_WIDTH); - m_pPropertyCombo->setFixedHeight(24); + m_pPropertyCombo->setMinimumHeight(24); m_pPropertyCombo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed); m_pPropertyCombo->setToolTip(tr("Display property")); @@ -506,7 +506,7 @@ void nmWxPebiResultControlBar::createUi() TIME_COMBO_MINIMUM_CONTENT_LENGTH); m_pTimeCombo->setSizeAdjustPolicy( QComboBox::AdjustToMinimumContentsLengthWithIcon); - m_pTimeCombo->setFixedHeight(24); + m_pTimeCombo->setMinimumHeight(24); m_pTimeCombo->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed); m_pTimeCombo->setToolTip(tr("Result time")); diff --git a/Src/nmNum/nmSubWxs/nmWxPerforationClosing.cpp b/Src/nmNum/nmSubWxs/nmWxPerforationClosing.cpp index 135668ea..d6d10980 100644 --- a/Src/nmNum/nmSubWxs/nmWxPerforationClosing.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPerforationClosing.cpp @@ -1,6 +1,7 @@ #include "nmWxPerforationClosing.h" #include +#include "nmDialogPreviewGuard.h" #include #include #include @@ -18,6 +19,7 @@ nmWxPerforationClosing::nmWxPerforationClosing(nmDataWellBase* pWellData, QWidge : iDlgBase(parent) { setWindowTitle(tr("Perforation closing intervals")); + new nmDialogPreviewGuard(this); setMinimumSize(500, 625); // 初始化成员变量 @@ -72,8 +74,10 @@ void nmWxPerforationClosing::initUI() // 创建工具栏容器 QWidget* toolbarContainer = new QWidget(this); - toolbarContainer->setFixedHeight(70); + toolbarContainer->setMinimumHeight(70); + toolbarContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QHBoxLayout* toolbarLayout = new QHBoxLayout(toolbarContainer); + toolbarLayout->setContentsMargins(0, 0, 0, 0); // 创建Add按钮组合 QWidget* addButtonContainer = new QWidget(this); @@ -91,7 +95,8 @@ void nmWxPerforationClosing::initUI() addContainerLayout->addWidget(m_pAddBtn, 0, Qt::AlignHCenter); addContainerLayout->addWidget(addTextLabel); - addButtonContainer->setFixedSize(100, 70); + addButtonContainer->setMinimumWidth(100); + addButtonContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); toolbarLayout->addWidget(addButtonContainer); // 创建Remove按钮组合 @@ -110,7 +115,8 @@ void nmWxPerforationClosing::initUI() removeContainerLayout->addWidget(m_pRemoveBtn, 0, Qt::AlignHCenter); removeContainerLayout->addWidget(removeTextLabel); - removeButtonContainer->setFixedSize(100, 70); + removeButtonContainer->setMinimumWidth(100); + removeButtonContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); toolbarLayout->addWidget(removeButtonContainer); // 添加复选框和时间单位控件组 diff --git a/Src/nmNum/nmSubWxs/nmWxPostprocessingAnimationWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPostprocessingAnimationWidget.cpp index 3c253736..52698420 100644 --- a/Src/nmNum/nmSubWxs/nmWxPostprocessingAnimationWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPostprocessingAnimationWidget.cpp @@ -1,6 +1,7 @@ #include "nmWxPostprocessingAnimationWidget.h" #include // 用于调试输出 #include // 用于 std::sort 排序算法 +#include "nmDialogPreviewGuard.h" // UI 相关的 Qt 头文件 #include @@ -134,6 +135,7 @@ nmContourResultDialog::nmContourResultDialog(QWidget *parent) { setWindowTitle(tr("Contour Pressure")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + new nmDialogPreviewGuard(this); m_resultLabel = new QLabel(this); m_resultLabel->setWordWrap(true); diff --git a/Src/nmNum/nmSubWxs/nmWxReservoirPropertiesEditor.cpp b/Src/nmNum/nmSubWxs/nmWxReservoirPropertiesEditor.cpp index 899d14dd..d7fb1383 100644 --- a/Src/nmNum/nmSubWxs/nmWxReservoirPropertiesEditor.cpp +++ b/Src/nmNum/nmSubWxs/nmWxReservoirPropertiesEditor.cpp @@ -212,7 +212,7 @@ QWidget* nmWxReservoirPropertiesEditor::createRibbonGroup( // 分组标题使用主题灰色和下划线,保持框架参考工具栏的层级表现。 QLabel* pCaptionLabel = new QLabel(sCaption, pGroupWidget); pCaptionLabel->setAlignment(Qt::AlignCenter); - pCaptionLabel->setFixedHeight(16); + pCaptionLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QFont oCaptionFont = pCaptionLabel->font(); oCaptionFont.setUnderline(true); pCaptionLabel->setFont(oCaptionFont); diff --git a/Src/nmNum/nmSubWxs/nmWxSensitive.cpp b/Src/nmNum/nmSubWxs/nmWxSensitive.cpp index 1a2ed1f8..b18ed03b 100644 --- a/Src/nmNum/nmSubWxs/nmWxSensitive.cpp +++ b/Src/nmNum/nmSubWxs/nmWxSensitive.cpp @@ -1,6 +1,7 @@ #include "nmWxSensitive.h" #include "nmDataAnalyzeManager.h" +#include "nmDialogPreviewGuard.h" #include "nmWxAutomaticFitting.h" #include "nmParameterField.h" #include "ZxBaseUtil.h" @@ -503,6 +504,7 @@ nmWxSensitivityShow::nmWxSensitivityShow( // 沿用原 Results 的白色表格及按钮布局,勾选在 Apply 或 OK 后生效。 setAttribute(Qt::WA_DeleteOnClose, false); setObjectName("nmSensitivityShowDialog"); + new nmDialogPreviewGuard(this); resize(700, 380); QVBoxLayout* layout = new QVBoxLayout(this); QTableView* table = m_table = new QTableView(this); @@ -598,6 +600,7 @@ nmWxSensitivityHistogramOptions::nmWxSensitivityHistogramOptions( // 复用运行表格;第四种在误差后追加拟合参数,选择变量后按原有 Apply/OK 流程生效。 setAttribute(Qt::WA_DeleteOnClose, false); setObjectName("nmHistogramOptions"); + new nmDialogPreviewGuard(this); setWindowTitle(tr("Histogram options")); resize(720, 400); QVBoxLayout* layout = new QVBoxLayout(this); @@ -680,6 +683,7 @@ nmWxSensitivityScatter::nmWxSensitivityScatter( setObjectName("nmSensitivityScatterPlot"); setAttribute(Qt::WA_DeleteOnClose, false); setWindowTitle(tr("Scatter plot")); + new nmDialogPreviewGuard(this); resize(850, 550); QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(8, 8, 8, 8); @@ -1435,6 +1439,7 @@ nmWxSensitive::nmWxSensitive(QWidget *parent, nmDataAnalyzeManager* manager) { // 关闭只隐藏,由所属分析统一销毁,重新打开保留当前输入。 setAttribute(Qt::WA_DeleteOnClose, false); + new nmDialogPreviewGuard(this); // 显式绑定所属分析窗口,后续切换窗口不会改变配置保存目标。 if (m_pDataManager) m_sensitiveData = m_pDataManager->getSensitiveDataCopy(); refreshModelValues(); @@ -2933,6 +2938,7 @@ void nmWxSensitive::onPreviewClicked() dialog->setAttribute(Qt::WA_DeleteOnClose, false); dialog->setWindowTitle(tr("Sensitivity Runs")); dialog->setWindowFlags(dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint); + new nmDialogPreviewGuard(dialog); dialog->setMinimumSize(420, 360); dialog->resize(470, 650); QVBoxLayout* layout = new QVBoxLayout(dialog); diff --git a/Src/nmNum/nmSubWxs/nmWxTimeDependentSkin.cpp b/Src/nmNum/nmSubWxs/nmWxTimeDependentSkin.cpp index 8fcfa394..bcd36785 100644 --- a/Src/nmNum/nmSubWxs/nmWxTimeDependentSkin.cpp +++ b/Src/nmNum/nmSubWxs/nmWxTimeDependentSkin.cpp @@ -1,5 +1,6 @@ #include "nmWxTimeDependentSkin.h" #include "nmWxPerforationClosing.h" +#include "nmDialogPreviewGuard.h" #include "nmWxPressFlowChartWidget.h" #include "nmWxChartWidget.h" @@ -150,6 +151,7 @@ nmWxTimeDependentSkin::nmWxTimeDependentSkin(nmDataWellBase* pWellData, QWidget } setWindowTitle(tr("Time Dependent Skin")); + new nmDialogPreviewGuard(this); setMinimumSize(1150, 800); // 初始化UI @@ -270,8 +272,11 @@ void nmWxTimeDependentSkin::initUI() // 创建工具栏容器 QWidget* toolbarContainer = new QWidget(this); - toolbarContainer->setFixedHeight(70); // 固定工具栏高度 + toolbarContainer->setMinimumHeight(70); + toolbarContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); m_pToolbarLayout = new QHBoxLayout(toolbarContainer); // 保存布局指针 + // 高度由图标、文字和字体共同决定,避免外层边距裁掉按钮下方文字。 + m_pToolbarLayout->setContentsMargins(0, 0, 0, 0); // 创建按钮并设置统一样式 auto createButton = [&](QPushButton*& button, const QString & iconPath, const QString & text) { @@ -294,8 +299,9 @@ void nmWxTimeDependentSkin::initUI() containerLayout->addWidget(button, 0, Qt::AlignHCenter); containerLayout->addWidget(textLabel); - // 设置容器的大小策略和固定高度 - buttonContainer->setFixedSize(100, 70); // 固定宽度和高度 + // 保留常规尺寸,大字体时允许布局按文字所需空间扩展。 + buttonContainer->setMinimumWidth(100); + buttonContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_pToolbarLayout->addWidget(buttonContainer); }; @@ -329,9 +335,9 @@ void nmWxTimeDependentSkin::initUI() checkboxLayout->addWidget(m_pShowDatesCheckBox); checkboxLayout->addWidget(m_pAddRateDependentCheckBox); - // 设置复选框容器的合适宽度以容纳三个复选框 - checkboxContainer->setFixedWidth(450); // 增加宽度以容纳水平排列的复选框 - checkboxContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + // 大字体或翻译文字较长时,按实际内容扩展复选框区域。 + checkboxContainer->setMinimumWidth(450); + checkboxContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); // 将复选框容器添加到工具栏布局 m_pToolbarLayout->addWidget(checkboxContainer); @@ -1295,7 +1301,8 @@ void nmWxTimeDependentSkin::createChartModeBtn() filterLayout->addWidget(m_pFilterBtn, 0, Qt::AlignHCenter); filterLayout->addWidget(filterLabel); - m_pFilterContainer->setFixedSize(100, 70); + m_pFilterContainer->setMinimumWidth(100); + m_pFilterContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_pFilterContainer->setVisible(false); m_pToolbarLayout->insertWidget(1, m_pFilterContainer); @@ -1316,7 +1323,8 @@ void nmWxTimeDependentSkin::createChartModeBtn() resetFilterLayout->addWidget(m_pResetFilterBtn, 0, Qt::AlignHCenter); resetFilterLayout->addWidget(resetFilterLabel); - m_pResetFilterContainer->setFixedSize(100, 70); + m_pResetFilterContainer->setMinimumWidth(100); + m_pResetFilterContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_pResetFilterContainer->setVisible(false); m_pToolbarLayout->insertWidget(2, m_pResetFilterContainer); @@ -1336,7 +1344,8 @@ void nmWxTimeDependentSkin::createChartModeBtn() resetLinesLayout->addWidget(m_pResetLinesBtn, 0, Qt::AlignHCenter); resetLinesLayout->addWidget(resetLinesLabel); - m_pResetLinesContainer->setFixedSize(100, 70); + m_pResetLinesContainer->setMinimumWidth(100); + m_pResetLinesContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_pResetLinesContainer->setVisible(false); m_pToolbarLayout->insertWidget(3, m_pResetLinesContainer); @@ -1458,7 +1467,8 @@ void nmWxTimeDependentSkin::createEditBoxes() editLayout->addLayout(dSkinLayout); // 设置容器大小 - editContainer->setFixedSize(180, 60); + editContainer->setMinimumWidth(180); + editContainer->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); editContainer->setStyleSheet( "QWidget {" "background-color: transparent;" diff --git a/Src/nmNum/nmSubWxs/nmWxWellEditor.cpp b/Src/nmNum/nmSubWxs/nmWxWellEditor.cpp index aab9c1f9..95f386b9 100644 --- a/Src/nmNum/nmSubWxs/nmWxWellEditor.cpp +++ b/Src/nmNum/nmSubWxs/nmWxWellEditor.cpp @@ -584,7 +584,7 @@ QWidget* nmWxWellEditor::createRibbonGroup( QLabel* pCaptionLabel = new QLabel(sCaption, pGroupWidget); pCaptionLabel->setAlignment(Qt::AlignCenter); - pCaptionLabel->setFixedHeight(16); + pCaptionLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); QFont oCaptionFont = pCaptionLabel->font(); oCaptionFont.setUnderline(true); pCaptionLabel->setFont(oCaptionFont); diff --git a/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculator.cpp b/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculator.cpp index 1c17d8b0..1f77b98a 100644 --- a/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculator.cpp +++ b/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculator.cpp @@ -39,8 +39,8 @@ nmWxWellboreStorageCalculator::~nmWxWellboreStorageCalculator() void nmWxWellboreStorageCalculator::initUI() { setWindowTitle(tr("Wellbore Storage Calculator")); - // 设置一个稍大的固定窗口尺寸,以容纳所有组件并保持对齐 - setFixedSize(500, 320); + // 保留默认尺寸,允许窗口随字体和布局所需空间扩展。 + setMinimumSize(500, 320); // 1. 创建模式选择的单选按钮和分组 m_pClosedChamberRadio = new QRadioButton(tr("Closed chamber")); diff --git a/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorTubingData.cpp b/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorTubingData.cpp index 179424dc..dc8cc5d3 100644 --- a/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorTubingData.cpp +++ b/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorTubingData.cpp @@ -1,6 +1,7 @@ #include "nmWxWellboreStorageCalculatorTubingData.h" #include +#include "nmDialogPreviewGuard.h" #include #include #include @@ -11,6 +12,7 @@ nmWxWellboreStorageCalculatorTubingData::nmWxWellboreStorageCalculatorTubingData(QWidget *parent) : iDlgBase(parent) { + new nmDialogPreviewGuard(this); this->initUI(); this->initConnections(); this->setupTableData(); @@ -40,7 +42,7 @@ double nmWxWellboreStorageCalculatorTubingData::getSelectedTubingID() const void nmWxWellboreStorageCalculatorTubingData::initUI() { setWindowTitle(tr("Tubing geometry data")); - setFixedSize(480, 450); + setMinimumSize(480, 450); QVBoxLayout* mainLayout = new QVBoxLayout(this); diff --git a/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorVolume.cpp b/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorVolume.cpp index 3c08d388..c66ef0ce 100644 --- a/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorVolume.cpp +++ b/Src/nmNum/nmSubWxs/nmWxWellboreStorageCalculatorVolume.cpp @@ -1,6 +1,7 @@ #include "nmWxWellboreStorageCalculatorVolume.h" #include +#include "nmDialogPreviewGuard.h" #include #include #include @@ -13,6 +14,7 @@ nmWxWellboreStorageCalculatorVolume::nmWxWellboreStorageCalculatorVolume(QWidget *parent) : iDlgBase(parent) { + new nmDialogPreviewGuard(this); this->initUI(); // 初始化用户界面 this->initConnections(); // 连接信号和槽 } @@ -24,7 +26,7 @@ nmWxWellboreStorageCalculatorVolume::~nmWxWellboreStorageCalculatorVolume() void nmWxWellboreStorageCalculatorVolume::initUI() { setWindowTitle(tr("Tested chamber volume")); - setFixedSize(450, 350); + setMinimumSize(450, 350); // 1. 主布局 QVBoxLayout* mainLayout = new QVBoxLayout(this);