Display image in qml using Image provider.
-
wrote on 2 Feb 2021, 13:14 last edited by
have created one application in that I want to received image from socket. Once it is received, it should display in QMl. 1:I am able to received Image from socket and display in QMl using image provider. But when I am trying to integrate this things on another application facing the following error :
QML QQuickItem: Cannot anchor a horizontal edge to a vertical edge. QML Connections: Cannot assign to non-existent property "onNewFrameReceived" ReferenceError: imageprovider is not defined.main.cpp: QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/qml/main.qml")); engine.addImageProvider(QLatin1String("imageprovider"), new QmlImageProvider()); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url);
In this file I have created one window and trying to load the other file name as qml_view.qml and here I am displaying one background image.
qml_view.qml: In this file i have divided into 3 parts. left container and right container and center container I want to show the image on center part of background image. I have created 1 button once that button press image received from socket should display. Item { id: name x: 25 y: 34 width: parent.width height: parent.height MouseArea { id: progressArea anchors.fill: progressBackground onClicked: { image.source = "image://imageprovider/cover" } } } Image { id: image anchors.left: text.right source: "" cache: false function reload() { var oldSource = source; source = ""; source = oldSource; console.log("reload") } } } }
-
You must be doing two mistakes
- Wrong anchor line assignments
- signal(framerecevd) specified may not exist in the component. There may be spelling mistake as well.
If you provide good working example, we can help. Above code does not show any of the problem you mentioned.
-
wrote on 2 Feb 2021, 18:36 last edited by
@Pooja-Bhusare said in Display image in qml using Image provider.:
engine.addImageProvider(QLatin1String("imageprovider"),
new QmlImageProvider());What is a QmlImageProvider()?
-
wrote on 3 Feb 2021, 05:15 last edited by
@dheerendra
sorry I cant share entire code but i will try to share some function -
@Pooja-Bhusare said in Display image in qml using Image provider.:
engine.addImageProvider(QLatin1String("imageprovider"),
new QmlImageProvider());What is a QmlImageProvider()?
wrote on 3 Feb 2021, 05:35 last edited by@fcarney QmlImageProvider is my class name
-
wrote on 3 Feb 2021, 05:45 last edited by
main.cpp int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QFontDatabase::addApplicationFont(":/fonts/DejaVuSans.ttf"); app.setFont(QFont("DejaVu Sans")); cluster=Cluster::instance(); QQmlApplicationEngine engine; QQmlContext *context = new QQmlContext(engine.rootContext()); engine.addImageProvider(QLatin1String("imageprovider"), new QmlImageProvider()); const QUrl url(QStringLiteral("qrc:/qml/main.qml")); engine.rootContext()->setContextProperty("Cluster",cluster); engine.load(url); return app.exec(); }
main.qml this is my main qml file here i am loading 1 background image and calling view.qml file Window { width: 1024 height: 600 title: qsTrId("title") visible: true Image { width: 1024 height: 600 source: "qrc:/src/bkg.jpg" Loader { width: 1024 height: 600 anchors.fill: parent asynchronous: true enabled: status == Loader.Ready source: "view.qml" visible: enabled } } }
view.qml This is my view .qml file here i have created image and call button if i pressed on call i can able to see the contact list but if i pressed on image button i cannot display image received through socket. Connections { target: imageprovider onNewFrameReceived: server_image.reload(); } Image { id:image_default x: 214 y: 0 width: 60 height: 60 source: "qrc:/src/Image-default.png" opacity: 0.5 MouseArea{ id : imagearea anchors.fill: parent onClicked: { console.log("In mouse area image loader function"); if(call_default.opacity ===1 ){ image_default.source="qrc:/src/Image-active.png" call_default.opacity = 0.5 call_default.source = "qrc:/src/phone-default.png" } else { console.log("In else part function"); image_default.source= "qrc:/src/Image-active.png" } image_default.z = 1 call_default.z = 0 image_default.opacity =1 backbutton.visible = true // server_image.source="image://imageprovider/cover" } } Image { id: server_image x: 137 y: 280 width: 190 height: 130 source: "" cache: false function reload() { var oldSource = source; source ="" source = oldSource; console.log("reload") } } }
tcpserver.h class MyTcpServer : public QObject { Q_OBJECT public: explicit MyTcpServer(QObject *parent = 0); signals: void valueChanged(int newValue); void newImageReceived(QImage); public slots: void newConnection(); void on_readyRead(); private: QTcpServer *server; int m_value; }; #endif // MYTCPSERVER_H
qmlimageprovider.h class QmlImageProvider : public QQuickImageProvider ,public QObject { public: QmlImageProvider(); QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; public slots: void updateImage(QImage new_image); private: QImage server_image; MyTcpServer *m; };
qmlimageprovider.cpp MyTcpServer::MyTcpServer(QObject *parent) : QObject(parent) { server = new QTcpServer(this); connect(server, SIGNAL(newConnection()), this, SLOT(newConnection())); connect(server,SIGNAL(readyRead()),this,SLOT(readyRead())); if(!server->listen(QHostAddress::Any, 9999)) { qDebug() << "Server could not start"; } else { qDebug() << "Server started!"; } } void MyTcpServer::newConnection() { QTcpSocket *socket = server->nextPendingConnection(); if(socket) { connect(socket ,SIGNAL(readyRead()),this,SLOT(on_readyRead())); socket->flush(); socket->waitForBytesWritten(3000); } } void MyTcpServer::on_readyRead() { QTcpSocket * server = dynamic_cast<QTcpSocket*>(sender()); if(server) { //read data from socket array.append(server->readAll()); if(array.size()<230400) { qDebug()<<"Array size " << array.size() ; } else { //read an image cv::Size const frame_size(240,320); img = cv::Mat(240,320, CV_8UC3,array.data()); cv::waitKey(5000); imdisplay=QImage ((uchar*)img.data, img.cols, img.rows, img.step, QImage::Format_RGB888); emit newImageReceived(imdisplay); } } } QmlImageProvider::QmlImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) { m = new MyTcpServer(); connect(m, &MyTcpServer::newImageReceived, this, &QmlImageProvider::updateImage); m->newConnection(); } QImage QmlImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { return server_image; } void QmlImageProvider::updateImage(QImage new_image) { server_image = new_image; }
-
wrote on 3 Feb 2021, 16:40 last edited by
@Pooja-Bhusare said in Display image in qml using Image provider.:
QQmlContext *context = new QQmlContext(engine.rootContext());
Why are you doing this? Don't do this. You don't need a separate context.
Connections { target: imageprovider onNewFrameReceived: server_image.reload(); }
imageprovider isn't a context property and doesn't need to be one.
onNewFrameReceived isn't a signal of your image provider class.
Why are you commenting this out?:
server_image.source="image://imageprovider/cover"QImage QmlImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { return server_image; } I going to return the same image regardless of your image://imageprovider/<value>. Use "id" to differentiate. This is fine if this is what you want. I don't know the networking side very well. I have used image providers a lot.
You might need to do this when your image updates. I am not sure if the image provider will signal a change in the image.
server_image.source="" server_image.source="image://imageprovider/cover"
This will force the update the image if it changed. I have had to do this.
1/7