1

I found a way to embed a QWidget in a QML, by using QQuickWidget render (anchoring, the QWidget with the QQuickWidget position), but I am trying to do the same using QQuickView/QmlApplicationEngine, which uses a different rendering system, and the QWidget is not shown.

Any ideas? Thanks in advance!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
laurapons
  • 971
  • 13
  • 32
  • Does this answer your question? [QPushButton export to QML](https://stackoverflow.com/questions/56425885/qpushbutton-export-to-qml) – eyllanesc Dec 01 '19 at 17:00
  • Currently it is not possible, previously the QML painting system was more compatible with Qt Widgets since it used QGraphicsScene but currently has another approach: Scene Graph. – eyllanesc Dec 01 '19 at 17:01
  • Probable duplicate of https://stackoverflow.com/questions/13014415/qt5-embed-qwidget-object-in-qml – Former contributor Dec 01 '19 at 18:52

1 Answers1

0

None of the posts linked on the comments answered my question. There is this small work around (for those who need it):

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine *engine = new QQmlApplicationEngine(&app);
    engine->load(QUrl("qrc:/qml/main.qml"));
    QQuickWindow* qmlwindow = qobject_cast<QQuickWindow *>(engine->rootObjects().first());

    CustomWidget *customwidget = new CustomWidget();
    QWindow* customwidgetwindow = QWindow::fromWinId(customwidget->winId());

    customwidgetwindow->setParent(qmlwindow);
    customwidget->show();

    if (window) {
        QQuickItem *qmlCustomWidget = qmlwindow->findChild<QQuickItem*>("qmlcustomwidget");
        if (qmlCustomWidget) {
            new WidgetAnchor(customwidgetwindow, qmlCustomWidget);
        }
    }

return app.exec();
}

Where CustomWidget is QWidget based class, and WidgetAnchor.cpp is:

WidgetAnchor::WidgetAnchor(QWidget* pWidget, QQuickItem* pItem)
    : QObject(pWidget),
      _pWidget(pWidget),
      _pQuickItem(pItem)
{
    connect(_pQuickItem, &QQuickItem::xChanged, this, &WidgetAnchor::updateGeometry);
    connect(_pQuickItem, &QQuickItem::yChanged, this, &WidgetAnchor::updateGeometry);
    connect(_pQuickItem, &QQuickItem::widthChanged, this, &WidgetAnchor::updateGeometry);
    connect(_pQuickItem, &QQuickItem::heightChanged, this, &WidgetAnchor::updateGeometry);
    updateGeometry();
}

void WidgetAnchor::updateGeometry() {
    if (_pQuickItem) {
        QRectF r = _pQuickItem->mapRectToItem(nullptr, QRectF(_pQuickItem->x(), _pQuickItem->y(), _pQuickItem->width(), _pQuickItem->height()));
    _pWidget->setGeometry(r.toRect());
    }
}

And on main.qml you have:

import QtQuick 2.0
import QtQuick.Window 2.3

Window {
    id: root
    visible: true
    width: 500; height: 500

    Item {
        objectName: "qmlcustomwidget"
        anchors.fill: parent
    }
}
laurapons
  • 971
  • 13
  • 32
  • `new WidgetAnchor(customwidgetwindow, qmlCustomWidget);` Passing `QWindow*` to `QWidget*` is obviously wrong. – Crawl.W Apr 29 '20 at 03:31
  • Is there any better approach you would suggest? – laurapons Apr 29 '20 at 10:37
  • If only to let the code pass,it can be corrected like this `WindowAnchor(QWindow* pWindow, QQuickItem* pItem)`. Prioritize widget nesting qml by `qquickwidget`. A small number of widgets can be anchored by this. I just pointed out the details of your answer are wrong. – Crawl.W Apr 30 '20 at 02:55