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.
- Crear una subclase
QQuickImageProvider; darle un miembroQImage(la imagen al proveedor), anularrequestImagepara proporcionar esa imagen (elidreal solicitado en realidad no importa, ver más abajo), y un espacio que recibe unQImagey actualiza el miembro. - Conecte su señal de
Publishera la ranura de su proveedor - Instale el proveedor en el motor QML a través de
QQmlEngine::addImageProvider(veaQQuickView::engine); de nuevo, laidrealidad no importa, solo use una sensible En QML, solo usa un elemento de
Imagesimple con una fuente como estaImage { id: myImage source: "image://providerIdPassedToAddImageProvider/foobar" }foobarpasará a su proveedor, pero una vez más, realmente no importa.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
Connectionsy un poco de JS.Tenga en cuenta que, en general, no necesita convertir
Publisherun tipo de QML, solo necesita crear una instancia en C ++ y exponerla al mundo QML a través deQQmlContext::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
- Subclase
QQuickPaintedItem: la subclase almacena laQImagepara pintar y tiene una ranura que establece la nueva QImage. También su implementación depaintsimplemente pinta la imagen usandoQPainter::drawImage. - Exponer la subclase al mundo QML a través de
qmlRegisterType(para que pueda usarlo en QML) 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
objectNamea algún valor, luego usafindChilden el objeto raíz (como lo devuelveQQuickView::rootObject()) para obtener un puntero al elemento mismo. Entonces puedes usarconnectcomo 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
Connectionsen 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
QImageen QML.