QtWebEngine:打印由 javascript 调用的网页
Posted
技术标签:
【中文标题】QtWebEngine:打印由 javascript 调用的网页【英文标题】:QtWebEngine: Printing a webpage invoked by javascript 【发布时间】:2015-10-19 15:10:13 【问题描述】:从here,我知道我可以使用QWebEngineView::render
,传递一个指向我的QPrinter 对象的指针以编程方式打印网页。
但如果打印请求是由 javascript 调用的(例如来自 window.print()
javascript 函数),我不知道如何捕获该请求然后将其移交给我的打印函数。
【问题讨论】:
【参考方案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 调用打印。我在上面链接到的建议黑客就是这样,一个黑客。以上是关于QtWebEngine:打印由 javascript 调用的网页的主要内容,如果未能解决你的问题,请参考以下文章