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