diff --git a/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h b/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h index 8924cd7f..f33ec6c7 100644 --- a/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h +++ b/Include/nmNum/nmSubWxs/nmWxNumericalDesign.h @@ -73,7 +73,6 @@ signals: void sigGenerateClicked(); // 点击生成按钮时发出的信号 // 敏感性批量任务交给所属主窗口,复用普通求解进度框。 void sigSensitivityTaskReady(nmWxSensitive* dialog, nmCalculationDllPebiSolverTask* task); - void sigSensitiveResultsRequested(); void sigIncludeWells(); // 包含其他井后刷新参数栏的信号 /** @brief 用户切换结果井时发送快照中的稳定井 UUID。 */ void sigResultWellChanged(const QString& sWellInstanceId); diff --git a/Include/nmNum/nmSubWxs/nmWxSensitive.h b/Include/nmNum/nmSubWxs/nmWxSensitive.h index de9cb30c..db22848c 100644 --- a/Include/nmNum/nmSubWxs/nmWxSensitive.h +++ b/Include/nmNum/nmSubWxs/nmWxSensitive.h @@ -25,6 +25,7 @@ class SensitivityDistributionPlot; class SensitivityResultsModel; class iGuiPlot; class QMenu; +class QAction; class NM_SUB_WXS_EXPORT nmWxSensitivityHistogramOptions : public iDlgBase { @@ -54,6 +55,7 @@ private slots: void updateThreshold(); void resetThreshold(); void adjustContextMenu(QMenu* menu); + void updateLegend(); private: QSharedPointer m_results; double m_baseError; @@ -62,6 +64,7 @@ private: QComboBox* m_parameter; double m_threshold; QLabel* m_legend; + QAction* m_resultsInPlot; iGuiPlot* m_plot; QVector m_points; QVector m_runRows; @@ -98,7 +101,6 @@ public: signals: void sigSensitivityTaskReady(nmWxSensitive* dialog, nmCalculationDllPebiSolverTask* task); void sigSensitivityCancelRequested(); - void sigSensitiveResultsRequested(); public slots: void reject() override; @@ -118,7 +120,6 @@ protected: void onPreviewClicked(); void onPreviewScrollAction(int action); void onSensitivityFinished(); - void onResultsClicked(); void onResultsChanged(); void onModelResultChanged(); @@ -149,7 +150,6 @@ private: QPushButton *generateButton; QPushButton *cancelButton; QPushButton *previewButton; - QPushButton *resultsButton; // 各个变量页面的控件列表 QList m_modeCombos; diff --git a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp index 67df7c75..198817c9 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp @@ -2013,7 +2013,7 @@ void nmSubWndMain::onShowSensitiveResults() curve->setVisible(!hidden.contains(curve->getName())); plot->setReadOnly(true); plot->freshAxisScales(true, false); - // 关闭后仍可通过 Results 恢复;只有新建或恢复窗口时才重新调整内部布局。 + // 只有新建或恢复窗口时才重新调整内部布局。 QMdiSubWindow* subWindow = nullptr; for(QWidget* parent = plot->parentWidget(); parent && !subWindow; parent = parent->parentWidget()) subWindow = qobject_cast(parent); @@ -2206,9 +2206,6 @@ void nmSubWndMain::updateSensitiveHistogramPlot() settings->setObjectName("nmHistogramOptionsButton"); options->addWidget(scatter); options->addWidget(settings); - QLabel* count = new QLabel(page); - count->setObjectName("nmHistogramCount"); - options->addWidget(count); options->addStretch(); layout->addLayout(options); iGuiPlot* plot = new iGuiPlot(true, page); @@ -2239,8 +2236,6 @@ void nmSubWndMain::updateSensitiveHistogramPlot() if(run.m_bSucceeded && !run.m_bCancelled && qIsFinite(run.m_dPressureRmse) && run.m_dPressureRmse >= 0.0) errors.append(run.m_dPressureRmse); } - window->findChild("nmHistogramCount")->setText(errors.isEmpty() - ? tr("No valid goodness-of-fit results") : tr("Valid runs: %1").arg(errors.size())); double minimum = 0.0, maximum = 1.0; if(!errors.isEmpty()) { minimum = maximum = errors.first(); diff --git a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp index 3773f957..3e506944 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp @@ -483,8 +483,6 @@ void nmSubWndUtils::setupNumericalDockWidgets(nmDataAnalyzeManager* pDataManager pSubWndMain, SLOT(onGenerateButtonClicked())); connect(pAnalWx, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*)), pSubWndMain, SLOT(onSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*))); - connect(pAnalWx, SIGNAL(sigSensitiveResultsRequested()), - pSubWndMain, SLOT(onShowSensitiveResults())); connect(pAnalWx, SIGNAL(sigResultWellChanged(QString)), pSubWndMain, SLOT(onWellSelected(QString))); diff --git a/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp b/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp index d5479d00..7cdb5476 100644 --- a/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp +++ b/Src/nmNum/nmSubWxs/nmWxNumericalDesign.cpp @@ -1464,7 +1464,6 @@ void nmWxNumericalDesign::onSensitiveClicked() // 按数值生成按钮的现有路径,将任务请求转发给所属主窗口。 connect(dlg, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*)), this, SIGNAL(sigSensitivityTaskReady(nmWxSensitive*,nmCalculationDllPebiSolverTask*))); - connect(dlg, SIGNAL(sigSensitiveResultsRequested()), this, SIGNAL(sigSensitiveResultsRequested())); dlg->show(); } diff --git a/Src/nmNum/nmSubWxs/nmWxSensitive.cpp b/Src/nmNum/nmSubWxs/nmWxSensitive.cpp index 4fcd3d53..715c8424 100644 --- a/Src/nmNum/nmSubWxs/nmWxSensitive.cpp +++ b/Src/nmNum/nmSubWxs/nmWxSensitive.cpp @@ -37,6 +37,7 @@ #include "tCurvePlotView.h" #include "iCurveDesc.h" #include +#include #include #include #include @@ -516,11 +517,12 @@ nmWxSensitivityScatter::nmWxSensitivityScatter( layout->addWidget(m_plot); // 两项固定图例不使用框架的分组标题,覆盖在绘图区左上角。 m_legend = new QLabel(m_plot->m_pPlotView->viewport()); - m_legend->setText("
□" + tr("sensitivity data") - + "
■" + tr("reference") + "
"); m_legend->setStyleSheet("QLabel { background: white; color: black; border: 1px solid #cccccc; }"); m_legend->setAttribute(Qt::WA_TransparentForMouseEvents); - m_legend->adjustSize(); + m_resultsInPlot = new QAction(tr("Results in plot"), this); + m_resultsInPlot->setCheckable(true); + connect(m_resultsInPlot, SIGNAL(toggled(bool)), this, SLOT(updateLegend())); + updateLegend(); m_plot->m_pPlotView->viewport()->installEventFilter(this); connect(m_parameter, SIGNAL(currentIndexChanged(int)), this, SLOT(updateParameter())); connect(m_plot->m_pPlotView, SIGNAL(sigAdjustContextMenu(QMenu*)), this, SLOT(adjustContextMenu(QMenu*))); @@ -608,22 +610,13 @@ void nmWxSensitivityScatter::updateParameter() void nmWxSensitivityScatter::updateThreshold() { - // 阈值以下的点填黑,范围使用这些采样点的参数值,不包含蓝色基准点。 + // 阈值以下的点填黑,并同步图例中的阈值显示。 if(m_parameter->currentIndex() < 0) return; + updateLegend(); QVector accepted; - double lower = 0.0, upper = 0.0; for(int i = 0; i < m_points.size(); ++i) if(m_points[i].y() < m_threshold) { - if(accepted.isEmpty()) lower = upper = m_points[i].x(); - lower = qMin(lower, m_points[i].x()); - upper = qMax(upper, m_points[i].x()); accepted.append(m_points[i]); } - const int index = m_parameter->itemData(m_parameter->currentIndex()).toInt(); - const nmDataSensitive::VariableSampling& variable = m_results->m_variables[index]; - m_plot->setToolTip(tr("Threshold: %1 MPa\n").arg(m_threshold, 0, 'g', 6) - + tr("Below threshold: %1 / %2; %3 range: %4").arg(accepted.size()).arg(m_points.size()) - .arg(variable.m_varName).arg(accepted.isEmpty() ? tr("N/A") - : QString::number(lower, 'g', 6) + " - " + QString::number(upper, 'g', 6) + " " + variable.m_modelValue.getUnit())); if(m_threshold > m_plot->getAxisOf(1)->getRangeMax()) { VecDouble ticks; const double top = m_threshold * 1.1; @@ -670,9 +663,21 @@ void nmWxSensitivityScatter::resetThreshold() void nmWxSensitivityScatter::adjustContextMenu(QMenu* menu) { // 复用绘图右键菜单,保留框架的缩放、复制与导出入口。 + menu->addAction(m_resultsInPlot); menu->addAction(tr("Reset line"), this, SLOT(resetThreshold())); } +void nmWxSensitivityScatter::updateLegend() +{ + // 勾选后在原有两项图例下追加阈值,拖线和重置时实时更新。 + QString text = "
□" + tr("sensitivity data") + + "
■" + tr("reference") + "
"; + if(m_resultsInPlot->isChecked()) + text += "
" + tr("Threshold: %1 MPa").arg(m_threshold, 0, 'g', 6) + "
"; + m_legend->setText(text); + m_legend->adjustSize(); +} + bool nmWxSensitivityScatter::eventFilter(QObject* object, QEvent* event) { if(object != m_plot->m_pPlotView->viewport()) return iDlgBase::eventFilter(object, event); @@ -707,7 +712,8 @@ bool nmWxSensitivityScatter::eventFilter(QObject* object, QEvent* event) .arg(run.m_dPressureRmse, 0, 'g', 6), view->viewport()); return true; } - QToolTip::showText(help->globalPos(), m_plot->toolTip(), view->viewport()); + QToolTip::hideText(); + event->ignore(); return true; } return iDlgBase::eventFilter(object, event); @@ -1173,7 +1179,7 @@ nmWxSensitive::nmWxSensitive(QWidget *parent, nmDataAnalyzeManager* manager) loadDataToUI(); m_loading = false; onTreeItemChanged(nullptr, 0); - // 已有批次可直接重新打开,结果发布后同步入口与列表。 + // 结果发布或清除后,同步本窗口持有的批次数据。 if(m_pDataManager) { connect(m_pDataManager, SIGNAL(sigSensitiveResultsChanged()), this, SLOT(onResultsChanged())); connect(m_pDataManager, SIGNAL(sigPebiResultSnapshotChanged()), this, SLOT(onModelResultChanged())); @@ -1694,11 +1700,9 @@ void nmWxSensitive::setupUI() bottomLayout->addWidget(previewButton); bottomLayout->addStretch(); - resultsButton = new QPushButton(tr("Results"), this); generateButton = new QPushButton(tr("Generate"), this); cancelButton = new QPushButton(tr("Cancel"), this); - bottomLayout->addWidget(resultsButton); bottomLayout->addWidget(generateButton); bottomLayout->addWidget(cancelButton); @@ -1714,7 +1718,6 @@ void nmWxSensitive::createConnections() connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancelClicked())); connect(previewButton, SIGNAL(clicked()), this, SLOT(onPreviewClicked())); - connect(resultsButton, SIGNAL(clicked()), this, SLOT(onResultsClicked())); connect(calculationTypeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onCalculationTypeChanged(int))); @@ -2408,22 +2411,12 @@ void nmWxSensitive::onSensitivityFinished() QMessageBox::warning(ownerWindow, tr("Sensitivity"), message); } -void nmWxSensitive::onResultsClicked() -{ - // Results 只打开或恢复结果图,曲线显示由各图自己的 Show 控制。 - onResultsChanged(); - if(!resultsButton->isEnabled()) return; - emit sigSensitiveResultsRequested(); - hide(); -} - void nmWxSensitive::onResultsChanged() { - // 新模型清除旧批次后同步禁用结果入口。 + // 同步当前批次,新模型清除旧结果时也清除本地引用。 QSharedPointer results; if(m_pDataManager && m_pDataManager->getSensitiveData()) results = m_pDataManager->getSensitiveData()->getResults(); - resultsButton->setEnabled(!results.isNull()); m_sensitiveData.setResults(results); }