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), anularrequestImage
para proporcionar esa imagen (elid
real solicitado en realidad no importa, ver más abajo), y un espacio que recibe unQImage
y actualiza el miembro. - Conecte su señal de
Publisher
a la ranura de su proveedor - Instale el proveedor en el motor QML a través de
QQmlEngine::addImageProvider
(veaQQuickView::engine
); de nuevo, laid
realidad no importa, solo use una sensible En QML, solo usa un elemento de
Image
simple con una fuente como estaImage { id: myImage source: "image://providerIdPassedToAddImageProvider/foobar" }
foobar
pasará 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
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 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 laQImage
para pintar y tiene una ranura que establece la nueva QImage. También su implementación depaint
simplemente 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
objectName
a algún valor, luego usafindChild
en el objeto raíz (como lo devuelveQQuickView::rootObject()
) para obtener un puntero al elemento mismo. Entonces puedes usarconnect
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.