0

I'm trying to build an application consisting of multiple QMdiSubWindows that each contain a QQuickWidget and can be moved between different QMdiAreas. I'm able to create subwindows and display QML content inside them, but this content disappears when the subwindow is moved to a new MDI area. Example code follows.

// Constructor
MySubWindow::MySubWindow(QQmlComponent* qml_component, QQmlEngine* engine,
  QWidget* parent, Qt::WindowFlags flags) : QMdiSubWindow(parent, flags) {
  // Add to MDI area
  initial_area->addSubWindow(this);

  // Create child QML widget
  auto* qml_widget = new QQuickWidget(engine, this);
  setWidget(qml_widget);

  // Add QML content
  auto* qml_obj = qobject_cast<QQuickItem*>(qml_component->create(engine->rootContext()));

  auto* root_item = qml_widget->quickWindow()->contentItem();
  qml_obj->setParent(root_item);
  qml_obj->setParentItem(root_item);

  // Show subwindow
  showMaximized();
}

// Move subwindow to a new MDI area
void MySubWindow::set_area(QMdiArea* new_area) {
  mdiArea()->removeSubWindow(this);
  new_area->addSubWindow(this);

  showMaximized();
}

I'm using a simple QML component that contains a colored rectangle to test. I can see the rectangle when MySubWindow is created, but I get a blank white window after set_area() is called. I've tried to reparent my QML object after the move to contentItem like shown in the constructor, but this causes a segfault. Any thoughts?

Jacob
  • 15
  • 4
  • I'm curious about the segfault. Why would reparenting crash? Did the debugger help? – JarMan Jul 27 '23 at 18:44
  • I didn't see anything useful with GBD. The pointer to the new parent looked valid. I did see the message "cannot set parent new parent is in a different thread" at least once (but not every time?), and tried to use `moveToThread()` on the `QQuickWidget`, but didn't get anywhere. – Jacob Jul 28 '23 at 07:43

1 Answers1

0

I'm not sure why, but I was able to fix the issue by switching from QQuickWidget to QQuickView. The modified code follows:

// Constructor
MySubWindow::MySubWindow(QQmlComponent* qml_component, QQmlEngine* engine,
  QWidget* parent, Qt::WindowFlags flags) : QMdiSubWindow(parent, flags) {
  // Add to MDI area
  initial_area->addSubWindow(this);

  // Create child QML widget
  auto* qml_view = new QQuickView();
  auto* qml_widget = QWidget::createWindowContainer(qml_view, this);
  setWidget(qml_widget);

  // Add QML content
  auto* qml_obj = qobject_cast<QQuickItem*>(qml_component->create(engine->rootContext()));

  auto* root_item = qml_view->contentItem();
  qml_obj->setParent(root_item);
  qml_obj->setParentItem(root_item);

  // Show subwindow
  showMaximized();
}

// Move subwindow to a new MDI area
void MySubWindow::set_area(QMdiArea* new_area) {
  mdiArea()->removeSubWindow(this);
  new_area->addSubWindow(this);

  showMaximized();
}
Jacob
  • 15
  • 4