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
-
@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.
-
This is a very good example. I follow the code and it works exactly as I expected.
Thank you so much -
Hi, I just copied this example but I got some errors. in "backend.cpp" and "pixmapimage.cpp" . The errors are the same and:
error: undefined reference to `PixmapContainer::PixmapContainer(QObject*)'
What is the problem?
-
@yunus said in How to display a QPixmap/QImage in QML?:
What is the problem?
The problem is right there in the error message.
Where is PixmapContainer::PixmapContainer(QObject*) defined?
I guess you forgot to add the cpp file for PixmapContainer.Or change this line
explicit PixmapContainer(QObject *parent = 0);
to
explicit PixmapContainer(QObject *parent = 0) : QObject(parent) {}
-
@KroMignon It works, thank you!
-
@KroMignon said in How to display a QPixmap/QImage in QML?:
I found an alternative solution
So are you feeding that string to the "source" property of QML Image?
-
Thank a lot for your code example. Really appreciate.