I have a imageprovider object based in QQuickImageProvider class that with a requestImage function generates a QR image that is created with a qrencode library. That Image painted is showed in a qml page that I show in a display.
The code works well and paints the QR Image successfully whith the default string, but I want to update or refresh the QR image everytime I receive a new string to encript and show in display.
QQuickImageProvider doesn't have a public function to connect from another object, or maybe I don't know if exists.
There is a way to update the image everytime I receive a new data event?
There is a similar question in Example but I can't understand the way is resolved.
Here is the code I use:
imageprovider.h
#ifndef IMAGE_PROVIDER_H
#define IMAGE_PROVIDER_H
#include <QQuickImageProvider>
#include <QPixmap>
#include <QPainter>
class ImageProvider : public QQuickImageProvider
{
public:
ImageProvider();
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
void loadData(QString newdata);
private:
QString data;
};
#endif // IMAGE_PROVIDER_H
imageprovider.cpp
#include "imageprovider.h"
#include <QPainter>
#include <qrencode.h>
ImageProvider::ImageProvider() : QQuickImageProvider(QQuickImageProvider::Image) {
}
QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) {
int width = 120;
int height = 120;
QImage img(requestedSize.width() > 0 ? requestedSize.width() : width,
requestedSize.height() > 0 ? requestedSize.height() : height,
QImage::Format_RGB32);
//QRcode *qr = QRcode_encodeString("HELLO WORLD", 1, QR_ECLEVEL_L, QR_MODE_8, 1);
QRcode *qr = QRcode_encodeString(data.toStdString().c_str(), 1, QR_ECLEVEL_L, QR_MODE_8, 1);
if(0!=qr){
QPainter painter(&img);
QColor fg("black");
QColor bg("white");
painter.setBrush(bg);
painter.setPen(Qt::NoPen);
painter.drawRect(0,0,120,120);
painter.setBrush(fg);
const int s=qr->width>0?qr->width:1;
const double w=120;
const double h=120;
const double aspect=w/h;
const double scale=((aspect>1.0)?h:w)/s;
for(int y=0;y<s;y++){
const int yy=y*s;
for(int x=0;x<s;x++){
const int xx=yy+x;
const unsigned char b=qr->data[xx];
if(b &0x01){
const double rx1=x*scale, ry1=y*scale;
QRectF r(rx1, ry1, scale, scale);
painter.drawRects(&r,1);
}
}
}
QRcode_free(qr);
}
return img;
}
void ImageProvider::loadData(QString newdata)
{
data = newdata;
}
main.cpp
QGuiApplication app(argc, argv);
...
ImageProvider ImageProvider;
engine.addImageProvider(QLatin1String("ImageProvider"), &ImageProvider);
QRImage.qml
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.1
Image {
id: qr
source: "image://ImageProvider/"
sourceSize.width: 120
sourceSize.height: 120
cache: false
}
What I typically do in this case is to simply change the URL of the image provider including some random number, which is then ignored in the provider itelf. So change "image://ImageProvider/something" to "image://ImageProvider/somethingelse". I typically use a random number. This way, when the URL changes, the provider is queried again and your implementation of requestImage(...) is re-evaluated.