WebEngine Widgets 打印示例

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

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

运行示例

要从 Qt Creator 运行示例,请打开 欢迎 模式,然后从 示例 中选择示例。有关更多信息,请访问 构建和运行示例

简单的 HTML 页面

在这个示例中,我们创建了一个内部 HTML 页面,作为资源文件集合 (.qrc) 添加。此页面只显示一个 HTML 消息框,说明如何通过使用键盘快捷键或点击按钮来触发打印。按钮具有 JavaScript onclick 事件属性,它调用 JavaScript 的 window.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 中不是,因此我们使用 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() 槽作为 QWebEngineView::printFinished() 信号的处理器。我们检查 成功 ,并报告发生的任何错误。最后,我们调用 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

© 2024 Qt公司。此处包含的文档贡献的版权均归其所有者所有。本提供的文档受 GNU自由文档许可证版本1.3 的许可,该许可证由自由软件基金会发布。Qt和相应的标志是芬兰以及全球其他国家的 Qt公司 商标。所有其他商标均为其所有者的财产。