fix: 修复窗口文字裁切和预览残留,完善网格失败提示

- 修复时间变表皮系数、射孔关闭工具栏文字显示不全
- 调整 DFN 导入、井与储层编辑、井储计算及 PEBI 控件尺寸,适配不同字体
- 修复隐藏对话框在 Windows 任务栏预览中的残留
- 网格失败接入框架日志,增加井半径、边界和网格尺度检查
- 向网格及求解窗口传递简短失败原因,取消操作不记录失败
- 更新中文 TS/QM 和翻译提取标记,统一相关文件为 CRLF
develop
lh 1 day ago
parent f008f90a7d
commit 16c7387468

Binary file not shown.

@ -8902,4 +8902,30 @@ Average pressure in contour: %2 MPa</source>
<translation>模型已发生变化,请重新生成预测。</translation>
</message>
</context>
<context>
<name>nmPebiGridDiagnostics</name>
<message><source>Only two-dimensional grid input is supported.</source><translation>当前仅支持二维网格输入。</translation></message>
<message><source>Grid spacing must be finite and greater than zero (current value: %1).</source><translation>网格尺度必须为有限正数,当前值:%1。</translation></message>
<message><source>The boundary must contain at least three edges.</source><translation>工区边界至少需要三条边。</translation></message>
<message><source>Boundary edge %1 has missing or non-finite coordinates.</source><translation>边界第 %1 条边的坐标缺失或不是有限数值。</translation></message>
<message><source>Boundary edge %1 has zero length. Check coincident points and coordinate rounding.</source><translation>边界第 %1 条边长度为零,请检查重合点及坐标取整造成的重合。</translation></message>
<message><source>Vertical well %1 has missing or non-finite coordinates/radius.</source><translation>第 %1 口直井的坐标或井半径缺失,或不是有限数值。</translation></message>
<message><source>Vertical well %1 has invalid radius %2 m; it must be greater than zero.</source><translation>第 %1 口直井的半径 %2 m 无效,井半径必须大于零。</translation></message>
<message><source>Vertical well %1: radius %2 m is too small to represent at coordinates (%3, %4) m.</source><translation>第 %1 口直井的半径 %2 m 相对于坐标(%3,%4)m 过小,已超出浮点数的可分辨精度。</translation></message>
<message><source>Grid input capture/preparation failed. Check the boundary and participating wells.</source><translation>网格输入读取或准备失败,请检查工区边界及参与计算的井。</translation></message>
<message><source>Unable to load HX_NWTM.dll (Windows error %1). Check the DLL and its runtime dependencies.</source><translation>无法加载 HX_NWTM.dll(Windows 错误码 %1),请检查网格库及其运行库依赖。</translation></message>
<message><source>HX_NWTM_GRID is missing from the DLL (Windows error %1). Check the library version.</source><translation>网格库缺少 HX_NWTM_GRID 入口(Windows 错误码 %1),请检查库版本。</translation></message>
<message><source>The grid algorithm encountered an access violation (0xC0000005).</source><translation>网格算法内部发生内存访问异常(0xC0000005)。</translation></message>
<message><source>The grid algorithm returned empty grid data. Check the license and geometry inputs.</source><translation>网格算法返回了空网格,请检查授权文件及几何输入。</translation></message>
<message><source>The generated grid cannot be displayed: invalid points, cell indices or degenerate cells.</source><translation>生成的网格无法显示,可能存在无效节点、单元索引错误或退化单元。</translation></message>
<message><source>Grid calculation raised an exception: %1</source><translation>网格计算发生异常:%1</translation></message>
<message><source>Grid calculation raised an unknown exception.</source><translation>网格计算发生未知异常。</translation></message>
<message><source>Unable to capture the grid boundary. Check that the analysis has a boundary.</source><translation>无法读取工区边界,请确认当前分析已设置边界。</translation></message>
<message><source>Unable to capture well geometry. Check participating well types and fracture endpoints.</source><translation>无法读取井几何信息,请检查参与计算的井类型及裂缝端点。</translation></message>
<message><source>Unable to capture fault/fracture geometry.</source><translation>无法读取断层或裂缝几何信息。</translation></message>
<message><source>Participating wells do not match the grid well list. Check the primary well and included wells.</source><translation>参与计算的井与网格井列表不匹配,请检查主井及包含井设置。</translation></message>
<message><source>The grid result was discarded because the analysis inputs changed. Generate the grid again.</source><translation>划分期间分析输入已改变,本次网格未提交,请重新划分网格。</translation></message>
<message><source>Grid generation failed: %1</source><translation>网格划分失败:%1</translation></message>
<message><source>Check whether the well radius is too small, and check grid spacing and geometry positions.</source><translation>请检查井半径是否过小、网格尺度及几何位置是否合适。</translation></message>
</context>
</TS>

@ -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<vtkUnstructuredGrid> 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,

@ -20,6 +20,8 @@ public:
~nmCalculationPebiGridTask();
/** @brief 在主线程按版本提交后台局部结果;过期结果返回 false。 */
bool commitResult(nmDataAnalyzeManager* pDataManager);
/** @brief 返回已翻译的失败原因,供主线程在任务结束后显示。 */
QString failureMessage() const;
signals:
/** @brief 无论成功或失败均通知主线程结束本轮网格任务。 */

@ -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 从防抖开始登记建网活动,使同一分析的求解等待最终提交。 */

@ -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()) {

@ -12,6 +12,7 @@
#include <QHash>
#include "nmCalculationUtils.h"
#include "nmPebiGridDiagnostics.h"
#include "zxLogInstance.h"
#include "nmDataAnalyzeManager.h"
@ -1455,16 +1456,23 @@ bool nmCalculationPebiGrid::captureInputSnapshot(
static_cast<int>(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<HX_NWTM_GRID_Func>(
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);
}

@ -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()

@ -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));
}
}

@ -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);

@ -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());

@ -1,5 +1,6 @@
#include "nmWxAutomaticfittingStart.h"
#include <QtGui/QApplication>
#include "nmDialogPreviewGuard.h"
#include <QtCore/QEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QFont>
@ -398,6 +399,7 @@ nmWxAutomaticfittingStart::nmWxAutomaticfittingStart(QWidget *parent)
// 设置窗口属性
setWindowTitle(tr("Auto Fitting Progress"));
new nmDialogPreviewGuard(this);
setMinimumSize(1000, 650);
setModal(false);
}

@ -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);

@ -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);

@ -1,5 +1,6 @@
#include "nmWxForecast.h"
#include <QApplication>
#include "nmDialogPreviewGuard.h"
#include <QStyle>
#include <QSpacerItem>
#include <QSizePolicy>
@ -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();

@ -209,7 +209,7 @@ void nmWxPebiGridViewWidget::createUi()
QVariant(static_cast<int>(
nmVTKMeshLayer::DisplayMode_SurfaceWithEdges)));
m_pDisplayModeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_pDisplayModeCombo->setFixedHeight(24);
m_pDisplayModeCombo->setMinimumHeight(24);
m_pDisplayModeCombo->setSizePolicy(
QSizePolicy::Preferred, QSizePolicy::Fixed);

@ -467,7 +467,7 @@ void nmWxPebiResultControlBar::createUi()
QVariant(static_cast<int>(
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"));

@ -1,6 +1,7 @@
#include "nmWxPerforationClosing.h"
#include <QVBoxLayout>
#include "nmDialogPreviewGuard.h"
#include <QHBoxLayout>
#include <QSplitter>
#include <QTreeWidgetItem>
@ -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);
// 添加复选框和时间单位控件组

@ -1,6 +1,7 @@
#include "nmWxPostprocessingAnimationWidget.h"
#include <QDebug> // 用于调试输出
#include <algorithm> // 用于 std::sort 排序算法
#include "nmDialogPreviewGuard.h"
// UI 相关的 Qt 头文件
#include <QVBoxLayout>
@ -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);

@ -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);

@ -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);

@ -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;"

@ -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);

@ -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"));

@ -1,6 +1,7 @@
#include "nmWxWellboreStorageCalculatorTubingData.h"
#include <QTableWidget>
#include "nmDialogPreviewGuard.h"
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>
@ -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);

@ -1,6 +1,7 @@
#include "nmWxWellboreStorageCalculatorVolume.h"
#include <QTableWidget>
#include "nmDialogPreviewGuard.h"
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
@ -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);

Loading…
Cancel
Save