How to display a QPixmap/QImage in QML?



  • Hi all,

    I wonder if there is a way to display a QPixmap/QImage in QML with a Image instance?
    Like this:

    Item {
        Image {
            id: preview
            anchors.fill : parent
            fillMode: Image.PreserveAspectFit
            smooth: true
            source: myImageClasse.picture
        }
    ...
    }
    

    I have create a little application which hold images into DB.
    I want to display those images so I have create an QObject with a QPixmap property which holds the image.
    How can I pass this picture to my Image instance without have to create a QQuickImageProvider?
    Do I have to use another QML Type?

    Regards


  • Moderators

    @KroMignon said:

    How can I pass this picture to my Image instance without have to create a QQuickImageProvider?

    that's the most straight-forward solution so far.



  • @KroMignon Hi! Here is a skeleton for a simple approach:

    pixmapcontainer.h - pass around objects of this type between C++ and QML

    #ifndef PIXMAPCONTAINER_H
    #define PIXMAPCONTAINER_H
    
    #include <QObject>
    #include <QPixmap>
    
    class PixmapContainer : public QObject
    {
        Q_OBJECT
    public:
        explicit PixmapContainer(QObject *parent = 0);
        QPixmap pixmap;
    };
    
    #endif // PIXMAPCONTAINER_H
    

    backend.h - provides the pixmaps

    #ifndef BACKEND_H
    #define BACKEND_H
    
    #include <QObject>
    
    class Backend : public QObject
    {
        Q_OBJECT
    public:
        explicit Backend(QObject *parent = 0);
        Q_INVOKABLE QObject* getPixmapContainer() const;
    };
    
    #endif // BACKEND_H
    

    backend.cpp

    #include "backend.h"
    #include <QQmlEngine>
    #include "pixmapcontainer.h"
    
    Backend::Backend(QObject *parent) :
        QObject(parent)
    {
    }
    
    QObject *Backend::getPixmapContainer() const
    {
        PixmapContainer * pc = new PixmapContainer();
        pc->pixmap.load("/path/to/image.jpg");
        Q_ASSERT(!pc->pixmap.isNull());
        QQmlEngine::setObjectOwnership(pc, QQmlEngine::JavaScriptOwnership);
        return pc;
    }
    

    pixmapimage.h - QtQuick component to show pixmaps

    #ifndef PIXMAPIMAGE_H
    #define PIXMAPIMAGE_H
    
    #include <QQuickPaintedItem>
    #include <QPainter>
    #include "pixmapcontainer.h"
    
    class PixmapImage : public QQuickPaintedItem
    {
        Q_OBJECT
    public:
        PixmapImage(QQuickItem *parent = Q_NULLPTR);
        Q_INVOKABLE void setImage(QObject *pixmapContainer);
    
    protected:
        virtual void paint(QPainter *painter) Q_DECL_OVERRIDE;
    
    private:
        PixmapContainer m_pixmapContainer;
    };
    
    #endif // PIXMAPIMAGE_H
    

    pixmapimage.cpp

    #include "pixmapimage.h"
    
    PixmapImage::PixmapImage(QQuickItem *parent) :
        QQuickPaintedItem(parent)
    {
    }
    
    void PixmapImage::setImage(QObject *pixmapContainer)
    {
        PixmapContainer *pc = qobject_cast<PixmapContainer*>(pixmapContainer);
        Q_ASSERT(pc);
        m_pixmapContainer.pixmap = pc->pixmap;
        update();
    }
    
    void PixmapImage::paint(QPainter *painter)
    {
        painter->drawPixmap(0, 0, width(), height(), m_pixmapContainer.pixmap);
    }
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    
    #include "pixmapcontainer.h"
    #include "backend.h"
    #include "pixmapimage.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<PixmapContainer>("io.qt.forum", 1, 0, "PixmapContainer");
        qmlRegisterType<Backend>("io.qt.forum", 1, 0, "Backend");
        qmlRegisterType<PixmapImage>("io.qt.forum", 1, 0, "PixmapImage");
    
        QQmlApplicationEngine engine;
        Backend backend;
        engine.rootContext()->setContextProperty("backend", &backend);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.7
    import QtQuick.Controls 1.5
    import io.qt.forum 1.0
    
    ApplicationWindow {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        PixmapImage {
            id: pixmapImage
            anchors.fill: parent
        }
    
        Button {
            text: "Get Pixmap"
            onClicked: pixmapImage.setImage( backend.getPixmapContainer() )
        }
    }
    


  • @Wieland Thanks a lot for your code example. This was very interresting, but still to much overhead for my very simple use case!

    I found an alternative solution, which works fine for me. I post it as reply to my question if someone else has the same needs.
    To pass the QImage to QML, I simply serialize into a QByteArray like this:

    
    Q_PROPERTY(QString picture READ picture CONSTANT)
    
    ...
    
    const QString MyImageClasse::picture()
    {
       QImage myImage;
      // Some init code to setup the image (e.g. loading a PGN/JPEG, etc.)
      QByteArray bArray;
      QBuffer buffer(&bArray);
      buffer.open(QIODevice::WriteOnly);
      myImage.save(&buffer, "JPEG");
    
      QString image("data:image/jpg;base64,");
      image.append(QString::fromLatin1(bArray.toBase64().data()));
    
      return image;
    }
    
    ...
    
    

    Works for me (TM) ;-)

    Regards



  • @Wieland said in How to display a QPixmap/QImage in QML?:

    qmlRegisterType<PixmapContainer>("io.qt.forum", 1, 0, "PixmapContainer");
    qmlRegisterType<Backend>("io.qt.forum", 1, 0, "Backend");
    qmlRegisterType<PixmapImage>("io.qt.forum", 1, 0, "PixmapImage");

    @Wieland Why did you register the backend & container objects? Why would you access such objects in the QML? Just being curious...



  • @Julian-Guarin You're right, registering those wasn't necessary here.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.