- Qt 6.12
- Qt WebEngine
- Qt WebEngine Widgets Examples
- WebEngine Widgets PrintMe Example
- Qt 6.12.0 Reference Documentation

# WebEngine Widgets PrintMe Example

Demonstrates how to print web pages using Qt WebEngine Widgets.

PrintMe demonstrates how to use the QWebEnginePage and QPrintDialog classes to print a web page. Further, it shows how to implement print preview by using the QPrintPreviewDialog class. For completeness, it also illustrates how to trigger a printing request within JavaScript.

#### Running the Example

You can run the example from:

- Qt Creator

  Open the Welcome mode and select the example from Examples. For more information, see Qt Creator: Tutorial: Build and run.

- Qt Extension for Visual Studio Code

  Run the Qt: Open Qt examples command from the Command Palette, and select the example from the list. For more information, see Qt Extension for Visual Studio Code: Tutorial: Build and run.

#### Simple HTML Page

In this example, we create an internal HTML page that is added as a resource collection file (.qrc). The page shows only a small HTML message box that explains how to trigger printing by using keyboard shortcuts or clicking a button. The button has the JavaScript `onclick` event attribute that calls the JavaScript `window.print()` function.

     <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 Function

In the `main` function, we first instantiate a QWebEngineView and set the URL to our internal HTML page. Next, we create a `PrintHandler` instance and pass the requested page. For convenience, we also create keyboard shortcuts that can be used to call a print dialog or print preview dialog.

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

#### Print Handler

In the `PrintHandler` class, we first implement `printPreview()`, where we instantiate QPrintPreviewDialog. We need the QPrintPreviewDialog::paintRequested handle to generate a set of preview pages.

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

Now we can implement the `PrintHandler::printDocument()` slot, which is called in response to the QPrintPreviewDialog::paintRequested signal. To do actual painting on a printer, we call the QWebEngineView::print() function. Printing is an async operation in Chromium, but not in Qt, so we run a local event loop using QEventLoop::exec() to make sure printing is done before returning. User input is blocked, since clicking on a button while we're waiting for the print to finish can mess up the internal state and cause a crash.

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

To get notified about the result of printing job, we implement `PrintHandler::printFinished()` slot as handler of QWebEngineView::printFinished() signal. We check for `success` and report any errors that occurred. Finally, we call QEventLoop::quit() to exit out of the local event loop.

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

The last function we implement, `PrintHandler::print()`, is trivial, because it simply opens QPrintDialog and calls the previously implemented `PrintHandler::printDocument()`.

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

Example project @ code.qt.io