【问题标题】:QtWebEngine: Printing a webpage invoked by javascriptQtWebEngine:打印由 javascript 调用的网页
【发布时间】:2015-10-19 15:10:13
【问题描述】:

here,我知道我可以使用QWebEngineView::render,传递一个指向我的QPrinter 对象的指针以编程方式打印网页。

但如果打印请求是由 javascript 调用的(例如来自 window.print() javascript 函数),我不知道如何捕获该请求然后将其移交给我的打印函数。

【问题讨论】:

    标签: javascript qt printing qt5 qtwebengine


    【解决方案1】:

    两年后我终于想出了解决这个问题的办法。

    Qt 5.8 确实支持打印,但是选择完全忽略 javascript 调用的 window.print() 请求。

    解决方案是注入一些 javascript 来覆盖 window.print() 函数:

    class JavascriptInvokedPrintComm : public QWebChannel
    {
        Q_OBJECT
    public:
        JavascriptInvokedPrintComm(QObject *parent) : QWebChannel(parent)
        {
            registerObject("webEngineViewBridge", this);
        }
    
    public slots:
        void print()
        {
            emit printRequest();
        }
    
    signals:
        void printRequest();
    };
    
    class MyWebEngineView : public QWebEngineView
    {
        Q_OBJECT
    public:
        MyWebEngineView(QWdidget *parent) :  QWebEngineView(parent)
        {
            // Inject qwebchannel.js so that we can handle javascript invoked printing
            QWebEngineScript webChannelJs;
            webChannelJs.setInjectionPoint(QWebEngineScript::DocumentCreation);
            webChannelJs.setWorldId(QWebEngineScript::MainWorld);
            webChannelJs.setName("qwebchannel.js");
            webChannelJs.setRunsOnSubFrames(true);
            {
                QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js");
                webChannelJsFile.open(QFile::ReadOnly);
                webChannelJs.setSourceCode(webChannelJsFile.readAll());
            }
            page()->scripts().insert(webChannelJs);
    
            // Inject some javascript to override the window.print() function so that we can actually catch and handle
            // javascript invoked print requests
            QWebEngineScript overrideJsPrint;
            overrideJsPrint.setInjectionPoint(QWebEngineScript::DocumentCreation);
            overrideJsPrint.setWorldId(QWebEngineScript::MainWorld);
            overrideJsPrint.setName("overridejsprint.js");
            overrideJsPrint.setRunsOnSubFrames(true);
            overrideJsPrint.setSourceCode(
                        "window.print = function() { "
                        "   new QWebChannel(qt.webChannelTransport, function(channel) { "
                        "       var webEngineViewBridge = channel.objects.webEngineViewBridge; "
                        "       webEngineViewBridge.print(); "
                        "   });"
                        "};"
                        );
            page()->scripts().insert(overrideJsPrint);
    
            JavascriptInvokedPrintComm *jsInvokedPrintComm = new JavascriptInvokedPrintComm(this);
            connect(jsInvokedPrintComm, &JavascriptInvokedPrintComm::printRequest, [this]()
            {
                QPrintDialog *prntDlg = new QPrintDialog(this);
                if(!prntDlg->exec())
                {
                    prntDlg->deleteLater();
                    return;
                }
    
                page()->print(prntDlg->printer(),
                    [prntDlg](bool ok)
                    {
                        Q_UNUSED(ok);
                        prntDlg->deleteLater();
                    }
                );
            });
        }
    }
    

    *未经过编译测试,但概念上应该可以工作

    【讨论】:

    • 那么我如何在 QML 文件中使用MyWebEngineView
    • 我不使用 QML,所以我不能给你细节,但我很确定你不会继承 QWebEngineView,而是继承 WebEngineView QML 类型。如果你不知道如何扩展 QML 类型,一个快速的谷歌找到了我:doc.qt.io/qt-5/qtqml-referenceexamples-coercion-example.html
    【解决方案2】:

    您使用哪个版本的 Qt?目前 5.6 版本不支持打印。

    查看计划:https://trello.com/c/JE5kosmC/72-printing-support

    【讨论】:

    • 我现在正在使用 5.5.1,但可能要等到 5.6 发布后才能完成我的项目。我从 qt.io 的支持人员那里听说,他们正在推动将 QtWebEngine 打印支持从 5.7 迁移到 5.6。我认为当包含真正的打印支持时,会出现 javascript 调用打印。我在上面链接到的建议黑客就是这样,一个黑客。
    猜你喜欢
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2011-02-27
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多