Qml ImageProvider & crashes
-
Hi everyone,
I'm currently broadening my Qt knowledge of QML.
For that purpose, I created a simple program. On QML side, a Window with a single Image in it and a cpp backend, that loads/creates images.
To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say.
And it works, I'm able to pass images from cpp to qml, BUT when I close the program, it crashes.
Heres the ImageProvider class
#ifndef SPIMAGEPROVIDER_H #define SPIMAGEPROVIDER_H #include <QObject> #include <QImage> #include <QQuickImageProvider> class SpImageProvider : public QObject, public QQuickImageProvider { Q_OBJECT public: SpImageProvider(); QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; public slots: void updateImage(const QImage &image); signals: void imageChanged(); private: QImage image; QImage no_image; }; #endif // SPIMAGEPROVIDER_H
#include "spimageprovider.h" SpImageProvider::SpImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) { no_image = QImage(200,200,QImage::Format_RGB32); no_image.fill(QColor("black")); } QImage SpImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { Q_UNUSED(id); if(image.isNull()) image = no_image; if(size){ *size = image.size(); } if(requestedSize.width() > 0 && requestedSize.height() > 0) { image = image.scaled(requestedSize.width(), requestedSize.height(), Qt::KeepAspectRatio); } return image; } void SpImageProvider::updateImage(const QImage &image) { if(this->image != image) { this->image = image; emit imageChanged(); } }
the main consists of this
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); SpImageProvider liveImageProvider; QQmlApplicationEngine engine; engine.addImageProvider("live", &liveImageProvider); engine.load(QUrl(QLatin1String("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
Crashlog
if i do not add the image provider to the engine, the program does not crash on exit
engine.addImageProvider("live", &liveImageProvider);
Am I Missing something in my code, or is this a bug I should report?
Greetings
-
@J.Hilk said in Qml ImageProvider & crashes:
To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say
You can pass image paths to QML and then no ImageProvider is necessary.
Regarding the crash: why do you set up the SpImageProvider as QObject? And why it is not being initialized in your constructor?
-
Hi everyone,
I'm currently broadening my Qt knowledge of QML.
For that purpose, I created a simple program. On QML side, a Window with a single Image in it and a cpp backend, that loads/creates images.
To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say.
And it works, I'm able to pass images from cpp to qml, BUT when I close the program, it crashes.
Heres the ImageProvider class
#ifndef SPIMAGEPROVIDER_H #define SPIMAGEPROVIDER_H #include <QObject> #include <QImage> #include <QQuickImageProvider> class SpImageProvider : public QObject, public QQuickImageProvider { Q_OBJECT public: SpImageProvider(); QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; public slots: void updateImage(const QImage &image); signals: void imageChanged(); private: QImage image; QImage no_image; }; #endif // SPIMAGEPROVIDER_H
#include "spimageprovider.h" SpImageProvider::SpImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) { no_image = QImage(200,200,QImage::Format_RGB32); no_image.fill(QColor("black")); } QImage SpImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) { Q_UNUSED(id); if(image.isNull()) image = no_image; if(size){ *size = image.size(); } if(requestedSize.width() > 0 && requestedSize.height() > 0) { image = image.scaled(requestedSize.width(), requestedSize.height(), Qt::KeepAspectRatio); } return image; } void SpImageProvider::updateImage(const QImage &image) { if(this->image != image) { this->image = image; emit imageChanged(); } }
the main consists of this
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); SpImageProvider liveImageProvider; QQmlApplicationEngine engine; engine.addImageProvider("live", &liveImageProvider); engine.load(QUrl(QLatin1String("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
Crashlog
if i do not add the image provider to the engine, the program does not crash on exit
engine.addImageProvider("live", &liveImageProvider);
Am I Missing something in my code, or is this a bug I should report?
Greetings
@J.Hilk
i guess you are not supposed to create the image provider instance on the stack.
Probably the QQmlEngine already deletes it and then it crashes when the runtime tries to delete it again when it goes out of scope.
So try:engine.addImageProvider("live", new SpImageProvider );
-
@J.Hilk
i guess you are not supposed to create the image provider instance on the stack.
Probably the QQmlEngine already deletes it and then it crashes when the runtime tries to delete it again when it goes out of scope.
So try:engine.addImageProvider("live", new SpImageProvider );
You're right, that is indeed the problem, originally I had it created on the heap, but wraped in a
QScopedPointer
which also results in a crash.But with a simple
SpImageProvider *liveImageProvider(new SpImageProvider()); engine.addImageProvider("live", liveImageProvider);
it works fine.
Seriously frustrating issue 😒
@sierdzio said in Qml ImageProvider & crashes:
@J.Hilk said in Qml ImageProvider & crashes:
To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say
You can pass image paths to QML and then no ImageProvider is necessary.
Regarding the crash: why do you set up the SpImageProvider as QObject? And why it is not being initialized in your constructor?
I know that, but the goal is to do some image manipulation after loading and than passing it along to the QML part to display it.
why do you set up the SpImageProvider as QObject
The image loader/processor and the image provider are each their own instance inside main and to pass new images from the loader/processor to the provider I connect them via Signal/Slot -> QObject inherritence requiered
And why it is not being initialized in your constructor?
True, I should look into that/fix it :)
-