将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
相关产品推荐
相关产品推荐

