c++ qt qml

Qt/QML: envíe QImage de C++ a QML y muestre la QImage en la GUI



(2)

QImage un Publisher clase que periódicamente emite un objeto QImage .

Sin embargo, estoy teniendo dificultades para dibujar QImage en un elemento QML. Parece que los componentes QML de Image y Canvas requieren un QUrl lugar de un QImage , pero no estoy seguro de cómo convertir mi QImage en un QUrl . Edit4: Cuando digo QUrl, no me refiero a que estoy tratando de convertir una imagen a una URL. Eso es una tontería. Quiero decir que quiero generar una referencia a esta imagen, que no está en el disco, y el tipo de datos que piden los componentes QML es una URL.

Investigué un poco y descubrí que QQuickImageProvider proporciona una solución, pero no he encontrado ninguna documentación que explique cómo convertir mi señal QImage en un QUrl que pueda usar para dibujar. Se apreciará cualquier código de ejemplo o documentación de referencia.

¡Gracias por tu ayuda!

Edit1:

He echado un vistazo aquí: http://qt-project.org/doc/qt-5.0/qtquick/qquickimageprovider.html y no veo cómo paso una QImage al proveedor de imágenes rápidas y de ella creo un QUrl .

Edit2. Aquí está el encabezado. La implementación no debería ser importante.

class Publisher { Q_OBJECT public: Publisher(QObject* parent = 0); virtual ~Publisher(void); Q_SIGNALS: void newImage(const QImage& newImage); };

Editar 3. Aquí está mi código QML, pero no sé cómo dibujar mi QImage, por lo que este código es algo sin sentido.

mi archivo main.cpp :

int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType<Publisher>("Components", 1, 0, "Publisher"); QtQuick2ApplicationViewer viewer; viewer.setMainQmlFile(QStringLiteral("qml/QQuickViewExample/main.qml")); viewer.showExpanded(); return app.exec(); }

mi archivo main.qml :

import QtQuick 2.0 import Components 1.0 Rectangle { id : testRect width: 360 height: 360 Image{ anchors.fill: parent id: myImage Publisher { id: myPub onNewImage: { myImage.source = newImage; #I know this doesnt work, it needs a QUrl and not a QImage } } } }


Cuando he tenido clases de C ++ para producir imágenes que he querido incorporar en QML, siempre lo he hecho al hacer que la clase C ++ sea una subclase de QDeclarativeItem (habrá un nuevo equivalente de QtQuick 2.0 por supuesto), anulando el método de pintura con el código de dibujo apropiado, que tal vez tan simple como

void MyItem::paint(QPainter* painter,const QStyleOptionGraphicsItem*,QWidget*) { painter->drawImage(QPointF(0.0f,0.0f),_image); }

si ya tiene una QImage del tamaño correcto ... y trabajo hecho. Para la animación, simplemente haga ping a la actualización () cuando haya algo nuevo que dibujar.


En otras palabras, ¿tiene una clase que emite una señal que lleva una QImage y desea actualizar un elemento en QML con esa imagen? Hay varias soluciones, ninguna de las cuales implica "convertir un QImage en un QUrl" (lo que sea que eso signifique, seguramente no necesita obtener una URL de data que transmita sus datos de imagen ...)

Use un proveedor de imágenes

Esto significa que puede usar un elemento de Image simple en sus archivos QML.

  1. Crear una subclase QQuickImageProvider ; darle un miembro QImage (la imagen al proveedor), anular requestImage para proporcionar esa imagen (el id real solicitado en realidad no importa, ver más abajo), y un espacio que recibe un QImage y actualiza el miembro.
  2. Conecte su señal de Publisher a la ranura de su proveedor
  3. Instale el proveedor en el motor QML a través de QQmlEngine::addImageProvider (vea QQuickView::engine ); de nuevo, la id realidad no importa, solo use una sensible
  4. En QML, solo usa un elemento de Image simple con una fuente como esta

    Image { id: myImage source: "image://providerIdPassedToAddImageProvider/foobar" }

    foobar pasará a su proveedor, pero una vez más, realmente no importa.

  5. Ya casi llegamos, ahora solo necesitamos una forma de enviar las actualizaciones de imágenes al mundo QML (de lo contrario, la imagen nunca sabrá cuándo actualizarse). Vea mi respuesta aquí para saber cómo hacer eso con un elemento Connections y un poco de JS.

    Tenga en cuenta que, en general, no necesita convertir Publisher un tipo de QML, solo necesita crear una instancia en C ++ y exponerla al mundo QML a través de QQmlContext::setContextProperty .

Use un artículo Qt Quick 2 personalizado

QQuickPaintedItem es probablemente el más conveniente para el trabajo, ya que ofrece un método de paint para tomar QPainter . Por lo tanto, el gran plan es

  1. Subclase QQuickPaintedItem : la subclase almacena la QImage para pintar y tiene una ranura que establece la nueva QImage. También su implementación de paint simplemente pinta la imagen usando QPainter::drawImage .
  2. Exponer la subclase al mundo QML a través de qmlRegisterType (para que pueda usarlo en QML)
  3. Encuentre una forma de conectar la señal que transporta la nueva imagen a la ranura de los artículos.

    Esta podría ser la parte difícil.

    Para realizar la conexión en C ++ necesita una forma de descubrir que el elemento ha sido creado (y obtener un puntero al mismo); generalmente uno hace esto asignando la propiedad objectName a algún valor, luego usa findChild en el objeto raíz (como lo devuelve QQuickView::rootObject() ) para obtener un puntero al elemento mismo. Entonces puedes usar connect como de costumbre.

    O , en su lugar, podría realizar la conexión en QML, al igual que arriba, a través de un elemento de Connections en el editor C ++ objeto expuesto al mundo QML:

    MyItem { id: myItem } Connections { target: thePublisherObjectExposedFromC++ onNewImage: myItem.setImage(image) }

    Esto tiene la ventaja de funcionar sin importar cuándo se crea la instancia de MyItem; pero no estoy 100% seguro de que funcionará porque no estoy seguro de que pueda manejar el tipo de QImage en QML.