qml qwidget qt5

Qt5. Incruste el objeto QWidget en QML



(6)

Estoy usando Qt5 beta y estoy tratando de incorporar un objeto QWidget en QML. El objetivo es usar QML tanto como sea posible, y solo usar objetos QWidget donde QML no hace lo que necesito. Encontré un enlace que explica cómo hacer esto para Qt4.7, pero no he encontrado ninguna información que explique cómo hacerlo en Qt5.

http://doc.qt.digia.com/4.7/declarative-cppextensions-qwidgets.html

El mismo ejemplo también está disponible en la carpeta de ejemplos de Qt5 en:

ejemplos / qtquick1 / declarative / cppextensions / qwidgets

Desafortunadamente, este ejemplo usa QtQuick 1, en lugar de QtQuick 2, y me gustaría usar las nuevas características de Qt5. De hecho, quiero insertar un widget qwt, pero como primer paso, me gustaría incluir cualquier objeto simple basado en QWidget.

¿Alguien puede ayudarme a obtener el ejemplo trabajando en Qt5 / QtQuick 2?


Además de la respuesta de Julien, una forma simple de lograr esto es usar QQuickWidget para mostrar la escena QML, y luego agregar un QWidget normal como elemento secundario de QQuickWidget. También puede agregar un QObject intermedio simple para anclar el QWidget a un elemento en la escena.

P.ej:

En main.qml:

Item { ... // layouts, extra items, what have you Item { objectName: "layoutItem" anchors.fill: parent } ... // more layouts, extra items, etc. }

widgetanchor.h:

class WidgetAnchor: public QObject { ptr<QWidget> _pWidget; QPointer<QQuickItem> _pQuickItem; public: 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(); } private: void updateGeometry() { if (_pQuickItem) { QRectF r = _pQuickItem->mapRectToItem(0, QRectF(_pQuickItem->x(), _pQuickItem->y(), _pQuickItem->width(), _pQuickItem->height())); _pWidget->setGeometry(r.toRect()); } } };

En main.cpp:

int main(int argc, char *argv[]) { QApplication app(argc, argv); auto pqw = new QQuickWidget; pqw->setSource(QUrl::fromLocalFile("main.qml")); pqw->setResizeMode(QQuickWidget::SizeRootObjectToView); pqw->setAttribute(Qt::WA_DeleteOnClose); auto pOwt = new MyWidget(pqw); if (auto pOverlayItem = pqw->rootObject()->findChild<QQuickItem*>("overlayItem")) new WidgetAnchor(pOwt, pOverlayItem); pqw->show(); return app.exec(); }

La documentación indica que el uso de QQuickWidget tiene ventajas sobre QQuickView y QWidget :: createWindowContainer, por ejemplo, sin restricciones en el orden de apilamiento, pero tiene un ''impacto de rendimiento menor''.

Espero que ayude.


El enfoque recomendado es permanecer con una aplicación basada en QWidget e incrustar las partes de QML usando QWidget :: createWindowContainer.


Lo que se puede hacer es renderizar el widget en una imagen y cargarlo como textura. Para la interacción, alguien debe reenviar eventos como mouseClick o keyPressed desde sceneGraph, traducir a coordenadas de widgets, pasar, renderizar y cargar textura nuevamente. Solo una idea :)


Puede incrustar QWidget en QML utilizando la clase QQuickPaintedItem: http://doc.qt.io/qt-5/qquickpainteditem.html

Qt5 tiene un ejemplo: http://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html

Debe implementar un QQuickPaintedItem inherente con un atributo de widget privado, que quiera incrustar. Proporcione el método de pintura, que solo renderiza el QtWidget y proporciona el mouse y otros eventos que transmiten desde la herencia de QQuickPaintedItem para incrustar QtWidget.

También hay QSG (Qt scene graph API), pero mi experiencia con esa cosa no fue fácil. Creo que la clave en el multihilo (realizar la representación en el hilo diferente (no en el hilo de la GUI de Qt, sin embargo, en Windows eso no es cierto y todo se hace en el hilo de la GUI principal).

Implementé la incrustación de QCustomPlot, aquí hay un enlace: github.com/mosolovsa/qmlplot


Here explica cómo agregar QComboBox en el diseño basado en QML. Piensa que será un buen ejemplo para tu caso. (En Qt 5.9 implementó el control nativo ComboBox QML).


Qt Quick 2 usa un gráfico de escena para una renderización eficiente en la GPU. Desafortunadamente, esto hace que sea imposible insertar widgets clásicos en la escena. El antiguo enfoque para incrustar tales widgets con la ayuda de QGraphicsProxyWidget funciona solo con Qt Quick 1, porque internamente utiliza QGraphicsView para todo el trabajo pesado y QGraphicsProxyWidget está destinado a ser utilizado con él.

A partir de ahora no hay planes para permitir la incorporación de QWidgets clásicos en el gráfico de escena que conozco. Creo que es poco probable que esto cambie, porque los conceptos de QPainter, el marco de la pintura utilizado para los widgets clásicos y el nuevo gráfico de escena no funcionan bien entre sí.

Hay algunos esfuerzos para desarrollar nuevos conjuntos de widgets específicamente diseñados para las necesidades de QML, pero ninguno de ellos es tan poderoso y maduro como los widgets clásicos. Los más destacados son los controles rápidos de QML , incluidos con Qt desde la versión 5.1.

Si realmente dependes de QWT, mi consejo sería seguir con Qt Quick 1.1 por ahora. Todavía está incluido con Qt 5, probablemente para casos como el tuyo. De esta forma, no aprovecharás el nuevo gráfico de escena.