QQuickImageProvider and updating an image more than once (PyQt5)



  • Hello All,

    So I have created a QML file which contains an image object within it, such as:

    ...
                    Image {
                        id: test
                        width: 500
                        height: 500
                        objectName: "test"
                        fillMode: Image.PreserveAspectFit
                        source: "image://myprovider/test.png"
                        cache: true
                    }
    ...
    
    

    In PyQt I have a class for the QQuickImageProvider such as:

    class MyImageProvider(QQuickImageProvider):
        def __init__(self):
            super(MyImageProvider, self).__init__(QQuickImageProvider.Image)
    
        # Here is where the image will be filled
        def requestImage(self, p_str, size):
            img = QImage(2048, 2048, QImage.Format_RGBA8888)
            img.fill(Qt.red) #Here's the magic...
            return img, img.size()
    

    And it gets called while starting the QML engine:

        # Prepare the QML engine
        app = QApplication(sys.argv)
        engine = QQmlApplicationEngine()
    
        provider = MyImageProvider()
        engine.addImageProvider("myprovider", provider)
    

    Now this works. Once. As soon as addImageProvider is called, the image turns red - which is expected!
    So under "MyImageProvider" I understand that the image is just filling with red (for the moment), but how can I access this ImageProvider and actually update the image with, say a file asynchonously from the code?

    Say for example, I create a function under MyImageProvider to load and image, such as LoadImg(self, str) I would do something like this...

     provider = MyImageProvider()
     engine.addImageProvider("myprovider", provider)
    ...
    ...
    provider.LoadImage('/path/to/image.png')
    

    The ImageProvider does not update. I'm assuming once this is called ' engine.addImageProvider("myprovider", provider)' that's the end of it. Whatever happens in 'requestImage' is what it is.

    So would I need to overload 'requestImage' and just have some sort of thread that updates the image or is there a way for me to call and update this image "on-the-fly" so-to-speak.

    Or am I approaching this all wrong?

    My ultimate goal here is to have a QML program with what would basically be a sub-window running within the main QML application (this I have now). Within that subwindow contains an image canvas that would update dynamically based on the PyQt side of things and stream a set of images to the subwindow . I would achieve this by eventually calling loadFromBytes from the QImage class in MyImageProvider, but I would also like for the image to update according to its status such as "Please Wait" or "Error Could not load images", and these two strings are actually PNG images that are scaled to fit. In order to do that, I have to find a way to call the ImageProvider class and have a function to update accordingly?

    In the PyQt side of the things, the subwindow is its own class and the "main window" calls it when a user selects a button.

    Now I'm not looking for code (although it always helps!) Just a point in the right direction :)
    The code above was taken from a sample elsewhere on the internet so I'm working off of that to begin with.

    And as always, thanks everyone!
    And if this is confusing, please let me know and I'll be more than happy to clarify anything.


Log in to reply