diff --git a/Include/nmNum/nmSubWnd/nmSubWndUtils.h b/Include/nmNum/nmSubWnd/nmSubWndUtils.h index a1e8f19..f9674b1 100644 --- a/Include/nmNum/nmSubWnd/nmSubWndUtils.h +++ b/Include/nmNum/nmSubWnd/nmSubWndUtils.h @@ -12,6 +12,7 @@ class iSubWnd; class iDockBaseWx; class ZxTabWidget; class QMdiSubWindow; +class ZxMdiSubWindow; class QEvent; class iSubWndFitting; @@ -136,6 +137,8 @@ public: void connectMdiActivation(iSubWndFitting* pSubWndF); // 单独关闭流动段分析页签时,移除仍引用其数据的画布图元 void detachFittingPlot(iSubWndFitting* pSubWndF); + // 关闭外层成果窗口时,提前解除其Map图元对分析数据的引用 + void detachMdiFittingPlots(ZxMdiSubWindow* pMdiChild); // 因为边界是可以旋转的,所以真实的顺序并非ee,se,we,ne,根据索引传递,查阅真实的,比如 ee,se,we,ne // xIndex 从1开始,如果矩形,则分别传入,1,2,3,4 如果是圆形,则传入1 @@ -148,6 +151,6 @@ public: // destroyed信号异步处理时,通过QObject地址取回析构前保存的分析窗口key QMap m_mapFittingKeys; - // 外层成果窗口关闭时,其画布由自身析构流程释放,不能再次主动遍历 + // 外层成果窗口关闭时,其画布已在MDI Close阶段清理,后续子窗口Close不再重复处理 QSet m_closingMdiChildren; }; diff --git a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp index 98c75e3..32f568e 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndMain.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndMain.cpp @@ -131,6 +131,15 @@ nmSubWndMain::nmSubWndMain(QWidget *parent, QString sExt) : nmSubWndMain::~nmSubWndMain() { + if(m_pWxPlot != nullptr) { + // Map窗口析构时,解除DataManager中保存的Plot引用,避免后续访问已释放画布。 + foreach(nmDataAnalyzeManager* pManager, nmDataAnalyzeManager::s_mapDataAnalManager.values()) { + if(pManager != nullptr && pManager->getPlot() == m_pWxPlot) { + pManager->setPlot(nullptr); + } + } + } + #ifdef QT_DEBUG // 坚持谁创建谁析构原则,删除(首先需要去除绑定) @@ -2423,6 +2432,7 @@ void nmSubWndMain::updateMapByDataManager(nmDataAnalyzeManager* pDataManager) return; } + // 一个Map同一时间只展示一个分析的数据,切换前先解除其他DataManager对当前Plot的绑定。 foreach(nmDataAnalyzeManager* pManager, nmDataAnalyzeManager::s_mapDataAnalManager.values()) { if(pManager != nullptr && pManager != pDataManager && pManager->getPlot() == m_pWxPlot) { pManager->setPlot(nullptr); diff --git a/Src/nmNum/nmSubWnd/nmSubWndSubWxsAnalyzeController.cpp b/Src/nmNum/nmSubWnd/nmSubWndSubWxsAnalyzeController.cpp index 2706a04..f2a3169 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndSubWxsAnalyzeController.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndSubWxsAnalyzeController.cpp @@ -40,6 +40,7 @@ void nmSubWndSubWxsAnalyzeController::updateWindowsForCurrentAnalyze(ZxMainWindo ZxTabWidget* pTabWx = pMainWindow->getCurTabWx(); QVector vecSubWnds = pMainWindow->getAllSubWndsOf(pTabWx); + // 本轮刷新只使用目标分析对应的数据中心,地图和网格保持同一个实例。 nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getInstanceByFitting(pCurSubWndF); foreach (iSubWnd* pSub, vecSubWnds) { nmSubWndMain* pMap = dynamic_cast(pSub); diff --git a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp index 8516ed6..a801532 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndUtils.cpp @@ -1,6 +1,5 @@ #include "zxLogInstance.h" #include "iRibbonXmlCmd.h" -#include #include #include #include @@ -1083,7 +1082,7 @@ void nmSubWndUtils::slotHandleTabChange(int index) if(nullptr != pMap) { // 更新地图相关信息 - pMap->updateMapByDataManager(nmDataAnalyzeManager::getInstanceByFitting(pSubWndF)); + pMap->updateMapByDataManager(pDataManger); } // TODO:网格更新 @@ -1091,8 +1090,8 @@ void nmSubWndUtils::slotHandleTabChange(int index) if(nullptr != pSubWndGrid) { // 更新网格 - disconnect(nmDataAnalyzeManager::getInstanceByFitting(pSubWndF), SIGNAL(dataChanged()), pSubWndGrid, SLOT(updateGrid())); - connect(nmDataAnalyzeManager::getInstanceByFitting(pSubWndF), SIGNAL(dataChanged()), pSubWndGrid, SLOT(updateGrid()), Qt::QueuedConnection); + disconnect(pDataManger, SIGNAL(dataChanged()), pSubWndGrid, SLOT(updateGrid())); + connect(pDataManger, SIGNAL(dataChanged()), pSubWndGrid, SLOT(updateGrid()), Qt::QueuedConnection); // 手动更新 pSubWndGrid->updateGrid(); } @@ -1184,12 +1183,40 @@ void nmSubWndUtils::detachFittingPlot(iSubWndFitting* pSubWndF) if(nmDataAnalyzeManager::getCurrentFitting() != pSubWndF) { nmDataAnalyzeManager* pCurManager = nmDataAnalyzeManager::getCurrentInstance(); if(pCurManager != nullptr) { + // 关闭的不是当前分析时,清掉待关闭分析图元后恢复当前分析的Map显示。 pCurManager->setPlot(pPlot); pPlot->setPlotsByDataManger(pCurManager); } } } +// 外层成果窗口关闭时,先清理仍绑定到Map上的图元 +void nmSubWndUtils::detachMdiFittingPlots(ZxMdiSubWindow* pMdiChild) +{ + if(pMdiChild == nullptr || m_pMainWnd == nullptr) { + return; + } + + ZxTabWidget* pTabWx = m_pMainWnd->getTabWxOf(pMdiChild); + if(pTabWx == nullptr) { + return; + } + + QVector vecSubWnds = m_pMainWnd->getAllSubWndsOf(pTabWx, "3004", true); + // 同一个成果内可能有多个分析,只清理仍占用Map Plot的DataManager。 + foreach(iSubWnd* pSubWnd, vecSubWnds) { + iSubWndFitting* pSubWndF = dynamic_cast(pSubWnd); + nmDataAnalyzeManager* pDataManager = nmDataAnalyzeManager::findManagerByFitting(pSubWndF); + if(pDataManager == nullptr || pDataManager->getPlot() == nullptr) { + continue; + } + + nmGuiPlot* pPlot = pDataManager->getPlot(); + pPlot->deleteAllPlotObjs(); + pDataManager->setPlot(nullptr); + } +} + // 流动段分析窗口销毁后,释放对应的数据管理器 void nmSubWndUtils::slotHandleFittingDestroyed(QObject* pObject) { @@ -1203,6 +1230,13 @@ void nmSubWndUtils::slotHandleMdiClosing(bool& bAllowClose) { if(!bAllowClose) { m_closingMdiChildren.remove(sender()); + return; + } + + // 用户确认关闭成果窗口后再清理Map,避免取消关闭时误清当前显示。 + ZxMdiSubWindow* pMdiChild = qobject_cast(sender()); + if(pMdiChild != nullptr) { + detachMdiFittingPlots(pMdiChild); } }