QML and C ++ image compatibility

I have looked through the documentation as well as everything I could find on the internet, but it looks like accessing the QML image from C ++ is not possible.

Is there a way to get around this?

+3


source to share


1 answer


This could have been done in QtQuick1, but this feature has been removed in QtQuick2.

The solution I came up with allows you to have the same image in QML and C ++ by implementing QQuickImageProvider

which basically works with QPixmap *

, which is converted to a string and then back to a pointer type (it sounds a bit unsafe, but it turns out that it is works very well).

class Pixmap : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString data READ data NOTIFY dataChanged)
public:
    Pixmap(QObject * p = 0) : QObject(p), pix(0) {}
    ~Pixmap() { if (pix) delete pix; }

    QString data() {
        if (pix) return "image://pixmap/" + QString::number((qulonglong)pix);
        else return QString();
    }

public slots:
    void load(QString url) {
        QPixmap * old = 0;
        if (pix) old = pix;
        pix = new QPixmap(url);
        emit dataChanged();
        if (old) delete old;
    }

    void clear() {
        if (pix) delete pix;
        pix = 0;
        emit dataChanged();
    }

signals:
    void dataChanged();

private:
    QPixmap * pix;
};

      

The implementation of the element is Pixmap

pretty straightforward, although the initial part was a bit limited, since the new pixmap was allocated to exactly the same memory address, the line data

was the same for different images, which caused the QML Image component not to update, but the solution was as simple as removing the old one pixmap only after a new one has been selected. Here is the actual image provider:

class PixmapProvider : public QQuickImageProvider {
public:
    PixmapProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {}
    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) {
        qulonglong d = id.toULongLong();
        if (d) {
            QPixmap * p = reinterpret_cast<QPixmap *>(d);
            return *p;
        } else {
            return QPixmap();
        }
    }
};

      



Check in:

//in main()
engine.addImageProvider("pixmap", new PixmapProvider);
qmlRegisterType<Pixmap>("Test", 1, 0, "Pixmap");

      

And this is how you use it in QML:

Pixmap {
    id: pix
}

Image {
    source: pix.data
}

// and then pix.load(path)

      

ALSO Note that in my case there was no actual pixmap modification that needed to be updated in QML. This solution will not automatically update the image in QML if changed in C ++ because the memory address will remain the same. But the solution for this is just as simple - implements a method update()

that allocates new QPixmap(oldPixmap)

- it will use the same internal data, but will give you a new accessor to it with a new memory address that will trigger the QML image to update the changes. This means that the suggested pixmap accessor will go through the class Pixmap

and not directly from QPixmap *

, as you will need the class Pixmap

to trigger the change data

, so just add an accessor forpix

and just in case you are doing complex or multi-threaded things, you can use QImage

and add a mutex instead so that the underlying data does not change in QML when changed to C ++ or vice versa.

+8


source







All Articles