You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将QOpenGLWidget父对象从QMainWindow改为QMdiSubWindow异常问题

Qt 5.12 OpenGL视图从独立窗口重新附加QMdiArea的解决方案

问题核心原因

你的问题出在父对象切换顺序错误以及未正确将QMdiSubWindow纳入MDI区域管理,导致视图的所有权仍被DetachedWindow持有,关闭独立窗口时会连带销毁视图;同时DetachedWindow因未彻底解除与视图的关联,无法正常关闭。

修正后的重新附加代码

// 1. 先切断视图与DetachedWindow的关联
VizWidget->setParent(nullptr);
detachWindow->setCentralWidget(nullptr);

// 2. 创建MDI子窗口并添加到MDI区域(Qt会自动处理父对象与窗口标志)
QMdiSubWindow* sw = m_mdiArea->addSubWindow(VizWidget);
sw->setAttribute(Qt::WA_DeleteOnClose);
// 同步视图尺寸到MDI子窗口
sw->resize(VizWidget->size());

// 3. 显示MDI子窗口并刷新视图
sw->showNormal();
VizWidget->update();

// 4. 安全关闭独立窗口
detachWindow->close();
// 若独立窗口无需复用,可直接销毁(需确保无其他引用)
// delete detachWindow;

关键修正点说明

  • 父对象切换顺序:必须先将视图的父设为nullptr,再解除DetachedWindow的centralWidget关联,彻底切断两者的所有权绑定。
  • 使用QMdiArea::addSubWindow:不要手动创建QMdiSubWindow后设置父对象,addSubWindow会自动处理子窗口的父对象、窗口标志等逻辑,确保视图正确纳入MDI管理。
  • 延迟关闭独立窗口:必须等视图完全转移到MDI后再关闭独立窗口,避免窗口销毁时误删视图。

补充:分离代码的优化建议(可选)

你的分离代码可简化,setCentralWidget会自动设置视图的父对象,无需手动调用view->setParent(newWid):

QMdiSubWindow* sw = m_mdiArea->activeSubWindow();
QTBVizWidget* view = qobject_cast<QTBVizWidget*>(sw->widget());
if (!view) return;

QRect globalRect = sw->mapToGlobal(sw->geometry().topLeft());
DetachedWindow* newWid = new DetachedWindow(nullptr, view);
newWid->setGeometry(globalRect.x(), globalRect.y(), view->width(), view->height());
newWid->setCentralWidget(view);

newWid->showNormal();
view->update();
m_mdiArea->removeSubWindow(sw);
// 若无需复用原MDI子窗口,可直接销毁
delete sw;

内容的提问来源于stack exchange,提问作者TopServicer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 20:55:20