QWebEngineView. Can't replace html code and print new pdf
-
I have 2 small html files. I've printed the first page successfully, but if I call
...->setHtml
again and place html code from another file and callprintToPdf
with a little modified filename, I see only the first file that was saved before. I've tested and on first pass it prints both htmls successfully. What's wrong?Here's the code:
QFile file("://cards_src/dentist_043_header.html"); file.open(QIODevice::ReadOnly); QTextStream input(&file); QString html = input.readAll(); file.close(); QFile file1("://cards_src/second_page_test.html"); file1.open(QIODevice::ReadOnly); QTextStream input1(&file1); QString html1 = input1.readAll(); file1.close(); // do some things ... webView->setHtml(html); QString path = QFileDialog::getSaveFileName(nullptr, "Сохранить в PDF", fileName + ".pdf", "PDF (*.pdf)"); if (QFileInfo(path).suffix().isEmpty()) path.append(".pdf"); webView->page()->printToPdf(path); webView->setHtml(html1); path.replace(".pdf", "_1.pdf"); webView->page()->printToPdf(path);
-
@JonB Yep, I've just found that I need to wait for loading page before printing and the solution is connect
loadFinished
signal to method I need, that doprintToPdf()
in it. I thought that WebEngineView does not need to wait for the local html file to load, but it was mistaken.UPD: Also, I've found a way to print multiple pdfs. You need to make a
QEventLoop
obj, connectloadFinished
signal toQEventLoop::quit
and aftersetHtml
just callloop.exec()
and you can guarantee that file you need will load and prints correctly only after loading of the previous page code.Example:
// Header class MyClass : public QObject { Q_OBJECT private: QEventLoop loop; QWebEngineView *webView; public: void saveCardPdf();
// Cpp MyClass::MyClass(QObject *parent ): QObject(parent) { webView = new QWebEngineView(); connect(webView, &QWebEngineView::loadFinished, &loop, &QEventLoop::quit); } ... void MyClass::saveCardPdf() { ... // Load your html code.. webView->setHtml(html); // html - string of one page loop.exec(); webView->page()->printToPdf(path); // Modify name for another file path.replace(".pdf", "_1.pdf"); webView->setHtml(html1); // html1 - string of another page loop.exec(); webView->page()->printToPdf(path); }
It's not perfect solution, but I think you understand the idea
-
@0x5FB5
I don't useQWebView
so this is a guess. I wonder whetherprintToPdf()
doesn't happen in the backgroubnd/asynchronously? In which case the web view's HTML must stay the same until the printing has finished? Only then can you change to a new HTML and print that. See e.g. https://stackoverflow.com/questions/59274653/how-to-print-from-qwebengineview. UseQWebEngineView::loadFinished
to wait for HTML to be loaded before printing? Or is there a "print finished" signal fromprintToPdf()
which you must wait for before proceeding with the second page? -
@JonB Yep, I've just found that I need to wait for loading page before printing and the solution is connect
loadFinished
signal to method I need, that doprintToPdf()
in it. I thought that WebEngineView does not need to wait for the local html file to load, but it was mistaken.UPD: Also, I've found a way to print multiple pdfs. You need to make a
QEventLoop
obj, connectloadFinished
signal toQEventLoop::quit
and aftersetHtml
just callloop.exec()
and you can guarantee that file you need will load and prints correctly only after loading of the previous page code.Example:
// Header class MyClass : public QObject { Q_OBJECT private: QEventLoop loop; QWebEngineView *webView; public: void saveCardPdf();
// Cpp MyClass::MyClass(QObject *parent ): QObject(parent) { webView = new QWebEngineView(); connect(webView, &QWebEngineView::loadFinished, &loop, &QEventLoop::quit); } ... void MyClass::saveCardPdf() { ... // Load your html code.. webView->setHtml(html); // html - string of one page loop.exec(); webView->page()->printToPdf(path); // Modify name for another file path.replace(".pdf", "_1.pdf"); webView->setHtml(html1); // html1 - string of another page loop.exec(); webView->page()->printToPdf(path); }
It's not perfect solution, but I think you understand the idea