c++qtraspberry-piqmlraspbian-buster

QML ImageProvider not displaying anything on Raspberry


I have a Qt/QML project that works fine on Windows. Recently, I added an option to display some images in QML. Since I need to set those from C++, I used ImageProvider for that. It works fine on Windows, but when I compile the project on Raspberry Pi (Buster, Qt 5.12.4), it doesn't display anything.

I tried to insert some logging at some places and figured out the requestImage doesn't ever get called.

Here's how the provider looks like:

class ImageProvider : public QQuickImageProvider {
    QImage image;
public:
    ImageProvider()
        : QQuickImageProvider(QQuickImageProvider::Image) {}

    void setImage(QImage img) {
        image = img;
    }

    QImage requestImage(const QString& id, QSize* /*size*/, const QSize& /*requestedSize*/) override {
        qInfo() << "Getting image from ImageProvider: " << id;
        return image;
    }
};

In QML, this is how it gets used:

Image {
    id: customImage
    source: ""
    anchors.fill : parent
    fillMode: Image.PreserveAspectFit

    Timer {
        id: refreshTimer
        interval: 20
        running: false
        repeat: false
        onTriggered: parent.source = "image://images/imageContent"
    }

    function refresh() {
        source = "";
        /* If an image is already displayed, it won't refresh
           if I set source to empty string and then right away 
           to an image provider again, it won't notice. It has to
           tick in the meantime... This is a workaround, maybe there's
           a better solution*/
        refreshTimer.start();
    }
    Connections {
        target: rootItem
        function onImageRefresh() {
            customImage.refresh();
        }
    }
}

I do register the image provider, but that should be clear from the fact it works on Windows:

engine.addImageProvider(QLatin1String("images"), new ImageProvider());

As you can see, I'm using a kind of workaround to be able to refresh the image when it changes, but that is most likely not the problem because again, it works on Windows. The problem is that the function simply does not ever get called on Raspberry Pi.

rootItem is the context so that I can emit a signal from the C++ backend class. It's setup like this:

engine.rootContext()->setContextProperty("rootItem", (QObject*)this);

Where this is an instance of a class having this signal:

signals:
    void imageRefresh();

I emit the signal from C++ like this:

emit view.imageRefresh();

But obviously the signal is never received on the QML side.


Solution

  • The reason it works on your Windows build but not your rPi is that you're using Qt 5.15 on Windows but 5.12 on your rPi. The code in your Connections block only works in 5.15. For some reason, Qt made a syntax change in 5.15 that broke backward compatibility. The older syntax should work on both, but I believe 5.15 will still nag you with warnings about it.

    So to fix the code using the older 5.12 syntax, change your Connections object to look like this:

        Connections {
            target: rootItem
            onImageRefresh: {
                customImage.refresh();
            }
        }