Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Display image in qml using Image provider.



  • 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")
                }
            }
        }
    }
    
    

  • Qt Champions 2017

    You must be doing two mistakes

    1. Wrong anchor line assignments
    2. 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.



  • @Pooja-Bhusare said in Display image in qml using Image provider.:

    engine.addImageProvider(QLatin1String("imageprovider"),
    new QmlImageProvider());

    What is a QmlImageProvider()?

    https://doc.qt.io/qt-5/qquickimageprovider.html



  • @dheerendra
    sorry I cant share entire code but i will try to share some function



  • @fcarney QmlImageProvider is my class name



  • 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;
    }
    
    


  • @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.


Log in to reply