WebEngine 小工具 PrintMe 示例

演示如何使用 Qt XMLWebEngine Widgets 打印网页。

PrintMe演示了如何使用QWebEnginePageQPrintDialog 类打印网页。此外,它还演示了如何使用QPrintPreviewDialog 类实现打印预览。为完整起见,它还说明了如何在 JavaScript 中触发打印请求。

运行示例

要从 Qt Creator,打开Welcome 模式,然后从Examples 中选择示例。更多信息,请参见Qt Creator: 教程:构建并运行

简单 HTML 页面

在此示例中,我们创建了一个内部 HTML 页面,并将其添加为资源集合文件 (.qrc) 。页面只显示一个小的 HTML 消息框,说明如何通过使用键盘快捷键或单击按钮来触发打印。按钮具有 JavaScriptonclick 事件属性,可调用 JavaScriptwindow.print() 函数。

<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>PrintMe</title>
      <link rel="stylesheet" type="text/css" href="style.css">
      <script>
      function printNow() {
         window.print();
      }
      </script>
   </head>
   <body>
      <form class="form">
         <div class="header">
            <h1>Hello Paper World!</h1>
            <h2>Press Ctrl+p to print with print preview</h2>
            <h2>Press Ctrl+Shift+p to print without print preview</h2>
            <h2>Click the button to print using JavaScript</h2>
            <p class="button" onclick="printNow()">Print Now</p>
         </div>
      </form>
   </body>
</html>

主要函数

main 函数中,我们首先实例化一个QWebEngineView ,并将 URL 设置为内部 HTML 页面。接着,我们创建一个PrintHandler 实例,并传递请求的页面。为方便起见,我们还创建了键盘快捷键,可用于调用打印对话框或打印预览对话框。

    QWebEngineView view;
    view.setUrl(QUrl(QStringLiteral("qrc:/index.html")));
    view.resize(1024, 750);
    view.show();

    PrintHandler handler;
    handler.setView(&view);

    auto printPreviewShortCut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_P), &view);
    auto printShortCut = new QShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_P), &view);

    QObject::connect(printPreviewShortCut, &QShortcut::activated, &handler, &PrintHandler::printPreview);
    QObject::connect(printShortCut, &QShortcut::activated, &handler, &PrintHandler::print);

PrintHandler 类中,我们首先实现printPreview() ,在此实例化QPrintPreviewDialog 。我们需要QPrintPreviewDialog::paintRequested 句柄来生成一组预览页面。

void PrintHandler::printPreview()
{
    if (!m_view)
        return;
    if (m_inPrintPreview)
        return;
    m_inPrintPreview = true;
    QPrintPreviewDialog preview(&m_printer, m_view);
    connect(&preview, &QPrintPreviewDialog::paintRequested,
            this, &PrintHandler::printDocument);
    preview.exec();
    m_inPrintPreview = false;
}

现在,我们可以实现PrintHandler::printDocument() 槽,它将响应QPrintPreviewDialog::paintRequested 信号而被调用。要在打印机上进行实际打印,我们需要调用QWebEngineView::print() 函数。在 Chromium 中,打印是一项异步操作,但在 Qt XML 中并非如此,因此我们使用QEventLoop::exec() 运行一个本地事件循环,确保打印完成后再返回。用户输入将被阻止,因为在等待打印完成的过程中点击按钮会扰乱内部状态并导致崩溃。

void PrintHandler::printDocument(QPrinter *printer)
{
    m_view->print(printer);
    // User input in the print preview dialog while we're waiting on a print task
    // can mess up the internal state and cause a crash.
    m_waitForResult.exec(QEventLoop::ExcludeUserInputEvents);
}

为了获得打印任务的结果通知,我们实现了PrintHandler::printFinished() slot 作为QWebEngineView::printFinished() 信号的处理程序。我们会检查success 并报告发生的任何错误。最后,我们调用QEventLoop::quit() 退出本地事件循环。

void PrintHandler::printFinished(bool success)
{
    if (!success) {
        QPainter painter;
        if (painter.begin(&m_printer)) {
            QFont font = painter.font();
            font.setPixelSize(20);
            painter.setFont(font);
            painter.drawText(QPointF(10,25),
                             QStringLiteral("Could not generate print preview."));
            painter.end();
        }
    }
    m_waitForResult.quit();
}

我们实现的最后一个函数PrintHandler::print() 是微不足道的,因为它只是打开QPrintDialog 并调用之前实现的PrintHandler::printDocument()

void PrintHandler::print()
{
    QPrintDialog dialog(&m_printer, m_view);
    if (dialog.exec() != QDialog::Accepted)
        return;
    printDocument(&m_printer);
}

示例项目 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.