0

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

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

4

2 回答 2

2

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

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();
                }
            );
        });
    }
}

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

于 2017-05-26T14:53:07.803 回答
0

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

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

于 2015-11-10T11:24:28.890 回答