qt - 如何在QWebView中显示动态创建的图像?

标签 qt webkit qwebview qwebengineview qresource

我正在使用 QtWebKit,在其中显示动态创建的 HTML 内容,并且我需要显示从数据库检索的图像。例如,如果我需要显示资源中的图像,我会将此行添加到我在 QWebView::setHtml 中使用的内容中:

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

效果很好,WebView 会自动查找资源并显示它。现在我需要用从数据库检索的内容替换该图像,并且文件系统中没有文件。如何做到这一点?

我可以管理动态添加内容的qrc命名空间吗?是否可以添加我自己的 QRC 处理程序来接收和服务来自 WebView 的请求?如果不是 QRC,是否有任何其他协议(protocol)可以用来向 WebView 中的图像提供内容?

我可以使用 setHtml 方法完全控制要添加到 WebView 的内容。

更新:我也想为QWebEngineView解决同样的问题。

最佳答案

QtWebkit

对于 QtWebkit,您必须使用 QNetworkAccessManager 拦截请求并重新发送自定义 QNetworkReply。

#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

在 QtWebEngine 中,您必须实现 QWebEngineUrlSchemeHandler,但不能使用 qrc、http 或 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();
}

关于qt - 如何在QWebView中显示动态创建的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63095511/

相关文章:

c++ - 调整 QMainwindow 大小以适合 Qdockwidget 大小

javascript - 使用 javascript 控制 css 适用于 Mozilla 和 Chrome,但不适用于 IE

javascript - 最小的 QWebChanel 示例不起作用

javascript - 无法从 QWebView 中的 Javascript 调用 Flash (Swf) 方法

c++ - QSqlRecord 在查询中将具有默认值的列设置为空

qt - 是否可以将 Qt 助手作为小部件嵌入到我的应用程序中?

css - 为什么 -webkit-text-stroke 在 Chrome 和 Safari 上看起来不同?

android kiosk 应用程序每两小时重新启动一次

qt - QWebView可以从Qt资源文件加载图像吗?

c++ - QAbstractItemModel 线程安全