I am trying to print a report from within my application, which involves both text and tables. Since QTextDocument
won\'t be sufficient, I\'ve decided to go with
In the first approach I think it fails because the HTML or url is not loaded yet and you want to print the text, so a possible solution is to use the loadFinished signal to start printing and use pdfPrintingFinished to know when the printing is finished.
#include <QtWebEngineWidgets>
class Widget : public QWidget
{
public:
explicit Widget(QWidget *parent = nullptr):
QWidget(parent), button(new QPushButton), progressbar(new QProgressBar), view(new QWebEngineView)
{
button->setText(tr("Press me"));
button->setEnabled(false);
connect(button, &QPushButton::clicked, this, &Widget::onClicked);
connect(view, &QWebEngineView::loadFinished, this, &Widget::onLoadFinished);
connect(view->page(), &QWebEnginePage::pdfPrintingFinished, this, &Widget::onPdfPrintingFinished);
QString html = R"(<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #ffffdffffd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #ffffdffffd;
}
</style>
</head>
<body>
<h2>HTML Table</h2>
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td>Italy</td>
</tr>
</table>
</body>
</html>
)";
view->setHtml(html);
auto lay = new QVBoxLayout(this);
lay->addWidget(button);
lay->addWidget(progressbar);
lay->addWidget(view);
resize(640, 480);
}
private:
void onLoadFinished(bool ok){
button->setEnabled(ok);
}
void onClicked(){
progressbar->setRange(0, 0);
QString fn = "/Users/s710/Downloads/test.pdf";
view->page()->printToPdf(fn);
}
void onPdfPrintingFinished(const QString & filename, bool ok){
qDebug() << filename << ok;
progressbar->setRange(0, 1);
}
private:
QPushButton *button;
QProgressBar *progressbar;
QWebEngineView *view;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
In the case where you use QPrinter I think that the error is caused because QPrinter is a local variable that is eliminated when the function is finished executing but Qt tries to access that variable asynchronously but the object does not exist. The solution is to extend the scope of QPrinter.
#include <QtWebEngineWidgets>
class Widget : public QWidget
{
public:
Widget(QWidget *parent = nullptr):
QWidget(parent), button(new QPushButton), progressbar(new QProgressBar), view(new QWebEngineView)
{
button->setText(tr("Press me"));
button->setEnabled(false);
connect(button, &QPushButton::clicked, this, &Widget::onClicked);
connect(view, &QWebEngineView::loadFinished, this, &Widget::onLoadFinished);
printer.setResolution(QPrinter::PrinterResolution);
printer.setOutputFormat(QPrinter::NativeFormat);
printer.setPaperSize(QPrinter::A4);
printer.setPageMargins(12, 16, 12, 20, QPrinter::Millimeter);
QString html = R"(<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #ffffdffffd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #ffffdffffd;
}
</style>
</head>
<body>
<h2>HTML Table</h2>
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
<tr>
<td>Ernst Handel</td>
<td>Roland Mendel</td>
<td>Austria</td>
</tr>
<tr>
<td>Island Trading</td>
<td>Helen Bennett</td>
<td>UK</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Yoshi Tannamuri</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Giovanni Rovelli</td>
<td>Italy</td>
</tr>
</table>
</body>
</html>
)";
view->setHtml(html);
auto lay = new QVBoxLayout(this);
lay->addWidget(button);
lay->addWidget(progressbar);
lay->addWidget(view);
resize(640, 480);
}
private:
void onLoadFinished(bool ok){
button->setEnabled(ok);
}
void onClicked(){
progressbar->setRange(0, 0);
QString fn = "/Users/s710/Downloads/test.pdf";
printer.setOutputFileName(fn);
view->page()->print(&printer, [this](bool ok){
qDebug() << ok;
progressbar->setRange(0, 1);
});
}
private:
QPushButton *button;
QProgressBar *progressbar;
QWebEngineView *view;
QPrinter printer;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}