2 votes

Comment afficher des images créées dynamiquement dans QWebView ?

Je travaille avec QtWebKit où j'affiche du contenu HTML créé dynamiquement, et j'ai besoin d'afficher les images que je récupère dans la base de données. Par exemple, si j'ai besoin d'afficher une image de la ressource, j'ajoute cette ligne au contenu que j'utilise en QWebView::setHtml :

<img src="qrc:/images/image.jpg"/>

Cela fonctionne très bien, WebView trouve automatiquement la ressource et l'affiche. Maintenant, je dois remplacer cette image par le contenu que je récupère dans la base de données, et qui n'a pas de fichier dans le système de fichiers. Comment faire ?

Puis-je gérer le qrc en ajoutant le contenu de manière dynamique ? Est-il possible d'ajouter mon propre gestionnaire QRC qui recevrait et servirait les demandes de WebView ? Si ce n'est pas QRC, y a-t-il un autre protocole que je peux utiliser pour fournir le contenu aux images dans WebView ?

J'ai un contrôle total sur ce que j'ajoute au WebView en utilisant la fonction setHtml méthode.

Mise à jour : Je voudrais résoudre le même problème pour QWebEngineView également.

2voto

eyllanesc Points 79506

QtWebkit

Dans le cas de QtWebkit, vous devez intercepter la demande à l'aide d'un QNetworkAccessManager et renvoyer une QNetworkReply personnalisée.

#include <QtWebKitWidgets>

class CustomReply : public QNetworkReply{
public:
    explicit CustomReply(const QByteArray & content, const QByteArray & contentType, const QUrl & url):
        QNetworkReply(), m_content(content){
        offset = 0;
        setUrl(url);
        open(ReadOnly | Unbuffered);
        setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
        setHeader(QNetworkRequest::ContentLengthHeader, QVariant(m_content.size()));
        QTimer::singleShot(0, this, &CustomReply::dispatch);
    }
    bool isSequential() const{
        return true;
    }
    qint64 bytesAvailable() const{
        return m_content.size() - offset + QIODevice::bytesAvailable();
    }
public slots:
    void abort(){
    }
protected:
    qint64 readData(char *data, qint64 maxSize){
        if (offset < m_content.size()) {
            qint64 number = qMin(maxSize, m_content.size() - offset);
            ::memcpy(data, m_content.constData() + offset, number);
            offset += number;
            return number;
        } else
            return -1;
    }
private:
    void dispatch(){
        emit readyRead();
        emit finished();
    }
    QByteArray m_content;
    qint64 offset;
};

class NetworkAccessManager: public QNetworkAccessManager{
public:
    using QNetworkAccessManager::QNetworkAccessManager;
protected:
    QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData){
        qDebug() << request.url();
        if (request.url() == QUrl("qrc:/images/image.jpg")){

            QImage image(150, 150, QImage::Format_RGB32);
            image.fill(QColor("salmon"));

            QByteArray ba;
            QBuffer buffer(&ba);
            buffer.open(QIODevice::WriteOnly);
            image.save(&buffer, "JPEG");

            return new CustomReply(ba, "image/jpeg", request.url());
        }
        return QNetworkAccessManager::createRequest(op, request, outgoingData);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWebView view;
    view.resize(640, 480);
    view.show();

    view.page()->setNetworkAccessManager(new NetworkAccessManager);

    QString html = R"(<img src="qrc:/images/image.jpg">)";
    view.setHtml(html);
    return a.exec();
}

QtWebEngine

Dans QtWebEngine, vous devez implémenter un QWebEngineUrlSchemeHandler mais vous ne pouvez pas utiliser les schémas qrc, http ou https :

#include <QtWebEngineWidgets>

#define SCHEMENAME "so"

class Handler : public QWebEngineUrlSchemeHandler{
public:
    void requestStarted(QWebEngineUrlRequestJob *job){
        if(job->requestUrl() == QUrl("so:/images/image.jpg")){
            QImage image(150, 150, QImage::Format_RGB32);
            image.fill(QColor("salmon"));

            QBuffer *buffer = new QBuffer;
            buffer->open(QIODevice::WriteOnly);
            image.save(buffer, "JPEG");
            buffer->seek(0);
            buffer->close();

            job->reply("image/jpeg", buffer);
        }
    }
    static void registerUrlScheme(){
        QWebEngineUrlScheme webUiScheme(SCHEMENAME);
        webUiScheme.setFlags(QWebEngineUrlScheme::SecureScheme |
                             QWebEngineUrlScheme::LocalScheme |
                             QWebEngineUrlScheme::LocalAccessAllowed);
        QWebEngineUrlScheme::registerScheme(webUiScheme);
    }

};

int main(int argc, char *argv[])
{
    Handler::registerUrlScheme();

    QApplication a(argc, argv);
    QWebEngineView view;

    Handler handler;
    view.page()->profile()->installUrlSchemeHandler(SCHEMENAME, &handler);
    view.resize(640, 480);
    view.show();

    QString html = R"(<img src="so:/images/image.jpg">)";
    view.setHtml(html);

    return a.exec();
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X