QtWebEngine: печать веб-страницы, вызванной javascript

Из здесь я знаю, что могу использовать QWebEngineView::render, передав указатель на мой объект QPrinter в программно напечатать веб-страницу.

Но если запрос на печать был вызван javascript (например, из функции window.print() javascript), я не знаю, как перехватить этот запрос, чтобы затем передать его моей функции печати.


person Jason    schedule 19.10.2015    source источник


Ответы (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();
                }
            );
        });
    }
}

* Не проверено компиляцией, но концептуально это должно работать

person Jason    schedule 26.05.2017
comment
так как я могу использовать MyWebEngineView в файлах QML? - person Mahdi Khalili; 26.11.2018
comment
Я не использую QML, поэтому не могу дать вам подробностей, но я почти уверен, что вместо подкласса QWebEngineView вы бы подклассировали тип QML WebEngineView. Если вы не знаете, как расширять типы QML, быстрый поиск в Google нашел следующее: doc.qt.io/qt-5/qtqml-referenceexamples-coercion-example.html - person Jason; 27.11.2018

Какую версию Qt вы используете? В настоящее время печать не поддерживается в версии 5.6.

См. план: https://trello.com/c/JE5kosmC/72-printing-support

person Jusnoo    schedule 10.11.2015
comment
Сейчас я использую 5.5.1, но, вероятно, подожду выхода 5.6, прежде чем закончу свой проект. Я слышал от сотрудника службы поддержки qt.io, что они настаивают на переносе поддержки печати QtWebEngine с версии 5.7 на версию 5.6. Я предполагаю, что печать, вызванная javascript, появится, когда будет включена настоящая поддержка печати. Предлагаемый хак, на который я ссылался выше, — это просто хак. - person Jason; 11.11.2015