Qt:使用 HTML 在 QTextDocument 上设置背景图像以生成 pdf 文件
Qt: Set background image on QTextDocument using HTML to generate pdf file
我在这个问题上纠结了好几次。
我需要通过创建一个包含一些数据的 pdf 文件来创建报告。
所以我的计划是不使用 QTextCursor,而是使用 HTML + CSS 在我的 pdf 文件中创建内容。
不幸的是,我不能使用 QWebEngine 小部件解决方案,因为我正在编译到 MinGW 中并且设置 MVSC 2017 环境是一团糟。
遗憾的是,我必须使用 QTextDocument 及其 HTML 子集支持。
我的问题是我无法在我的 pdf 文件中放置背景图片。
我想把这张图片作为背景图片:
让我疯狂的是我使用 css 属性 在我的 pdf 文件中显示背景图像。
background-image: url(:/images/blue-gradient-background.jpg);
Qt 似乎考虑到了这一点,但它仍然不显示背景。
看看:
第一个 pdf 文件不包含 html 内容上的 css 属性 背景图像,但第二个包含并且您可以看到文件的大小更大所以它已经考虑了 css 属性。
但它没有显示背景:
左边是第一个文件,右边是第二个文件 css 属性.
我使用资源中的 html 文件生成报告:
<!DOCTYPE html>
<html>
<style>
body {
background-image: url(:/images/blue-gradient-background.jpg);
}
h1 {
color: blue;
}
#table-content {
}
#table-content table {
margin: 1em
}
</style>
<body>
<div align="center"><h1>[title-template]</h1></div>
<div align="center" id="table-content">[table-template]</div>
</body>
</html>
此 html 文件已在 class 的构造函数中打开并读取:
FileEditor::FileEditor()
{
QFile htmlTemplate(":/html/report.html");
if (htmlTemplate.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&htmlTemplate);
m_reportPageHTMLTemplate = in.readAll();
}
}
然后我使用自定义 class 和此功能,使用 QPrinter 和 QPainter 写入数据:
void FileEditor::writeReportPdfFile(const QString &i_path, const S12xConf &i_s12xConf, const S12xData &i_s12xData, const BenchTestData &i_benchTestData)
{
QDir directory(i_path); // we create a QDir with the path
if (!directory.exists()) // if the directory does not exist then
{
directory.mkpath("."); // we create the path
}
QString fileName = getCurrentHourDate() + "_S12xNG_Test_Report.pdf";
QPrinter pdfPrinter(QPrinter::HighResolution);
pdfPrinter.setOutputFormat(QPrinter::PdfFormat);
pdfPrinter.setPageSize(QPageSize(QPageSize::A4));
pdfPrinter.setOutputFileName(i_path + "/" + fileName);
pdfPrinter.setFullPage(true);
QPainter painter(&pdfPrinter);
painter.setBackgroundMode(Qt::OpaqueMode);
QTextDocument measuresDoc;
QTextDocument averagesDoc;
QTextDocument inOutDoc;
measuresDoc.documentLayout()->setPaintDevice(&pdfPrinter);
measuresDoc.setPageSize(pdfPrinter.pageRect().size());
averagesDoc.documentLayout()->setPaintDevice(&pdfPrinter);
averagesDoc.setPageSize(pdfPrinter.pageRect().size());
inOutDoc.documentLayout()->setPaintDevice(&pdfPrinter);
inOutDoc.setPageSize(pdfPrinter.pageRect().size());
setMeasuresTextDocument(&measuresDoc);
setAveragesTextDocument(&averagesDoc);
setInputsOutputsTextDocument(&inOutDoc);
measuresDoc.drawContents(&painter); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter); // We print the TextDocument of the Inputs/Outputs into the document
measuresDoc.undo();
averagesDoc.undo();
inOutDoc.undo();
}
这是将 html 数据添加到度量 QTextDocument 中的函数:
void FileEditor::setMeasuresTextDocument(QTextDocument *o_measuresDoc)
{
QString htmlContent = m_reportPageHTMLTemplate;
htmlContent.replace("[title-template]","I. Measures Data");
o_measuresDoc->setHtml(htmlContent);
}
所以我做错了什么?
预先感谢您的回复。
我找到答案了!
是关于QTextDocument的drawContents方法。
为了在文档中看到背景图像,您需要添加第二个参数。
它是一个 QRectF 对象,代表背景图像将被裁剪到的矩形的大小。
void QTextDocument::drawContents(QPainter *p, const QRectF &rect = QRectF())
Draws the content of the document with painter p, clipped to rect. If rect is a null rectangle (default) then the document is painted unclipped.
所以我做的是:
easuresDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Inputs/Outputs into the document
pdfPrinter.paperRect是没有边距的页面矩形。
此外,如果您希望背景图像按比例打印而不重复,则需要将打印机设置为 QPrinter::PrinterResolution
QPrinter pdfPrinter(QPrinter::PrinterResolution);
我在这个问题上纠结了好几次。 我需要通过创建一个包含一些数据的 pdf 文件来创建报告。 所以我的计划是不使用 QTextCursor,而是使用 HTML + CSS 在我的 pdf 文件中创建内容。 不幸的是,我不能使用 QWebEngine 小部件解决方案,因为我正在编译到 MinGW 中并且设置 MVSC 2017 环境是一团糟。 遗憾的是,我必须使用 QTextDocument 及其 HTML 子集支持。
我的问题是我无法在我的 pdf 文件中放置背景图片。
我想把这张图片作为背景图片:
让我疯狂的是我使用 css 属性 在我的 pdf 文件中显示背景图像。
background-image: url(:/images/blue-gradient-background.jpg);
Qt 似乎考虑到了这一点,但它仍然不显示背景。
看看:
第一个 pdf 文件不包含 html 内容上的 css 属性 背景图像,但第二个包含并且您可以看到文件的大小更大所以它已经考虑了 css 属性。
但它没有显示背景:
我使用资源中的 html 文件生成报告:
<!DOCTYPE html>
<html>
<style>
body {
background-image: url(:/images/blue-gradient-background.jpg);
}
h1 {
color: blue;
}
#table-content {
}
#table-content table {
margin: 1em
}
</style>
<body>
<div align="center"><h1>[title-template]</h1></div>
<div align="center" id="table-content">[table-template]</div>
</body>
</html>
此 html 文件已在 class 的构造函数中打开并读取:
FileEditor::FileEditor()
{
QFile htmlTemplate(":/html/report.html");
if (htmlTemplate.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&htmlTemplate);
m_reportPageHTMLTemplate = in.readAll();
}
}
然后我使用自定义 class 和此功能,使用 QPrinter 和 QPainter 写入数据:
void FileEditor::writeReportPdfFile(const QString &i_path, const S12xConf &i_s12xConf, const S12xData &i_s12xData, const BenchTestData &i_benchTestData)
{
QDir directory(i_path); // we create a QDir with the path
if (!directory.exists()) // if the directory does not exist then
{
directory.mkpath("."); // we create the path
}
QString fileName = getCurrentHourDate() + "_S12xNG_Test_Report.pdf";
QPrinter pdfPrinter(QPrinter::HighResolution);
pdfPrinter.setOutputFormat(QPrinter::PdfFormat);
pdfPrinter.setPageSize(QPageSize(QPageSize::A4));
pdfPrinter.setOutputFileName(i_path + "/" + fileName);
pdfPrinter.setFullPage(true);
QPainter painter(&pdfPrinter);
painter.setBackgroundMode(Qt::OpaqueMode);
QTextDocument measuresDoc;
QTextDocument averagesDoc;
QTextDocument inOutDoc;
measuresDoc.documentLayout()->setPaintDevice(&pdfPrinter);
measuresDoc.setPageSize(pdfPrinter.pageRect().size());
averagesDoc.documentLayout()->setPaintDevice(&pdfPrinter);
averagesDoc.setPageSize(pdfPrinter.pageRect().size());
inOutDoc.documentLayout()->setPaintDevice(&pdfPrinter);
inOutDoc.setPageSize(pdfPrinter.pageRect().size());
setMeasuresTextDocument(&measuresDoc);
setAveragesTextDocument(&averagesDoc);
setInputsOutputsTextDocument(&inOutDoc);
measuresDoc.drawContents(&painter); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter); // We print the TextDocument of the Inputs/Outputs into the document
measuresDoc.undo();
averagesDoc.undo();
inOutDoc.undo();
}
这是将 html 数据添加到度量 QTextDocument 中的函数:
void FileEditor::setMeasuresTextDocument(QTextDocument *o_measuresDoc)
{
QString htmlContent = m_reportPageHTMLTemplate;
htmlContent.replace("[title-template]","I. Measures Data");
o_measuresDoc->setHtml(htmlContent);
}
所以我做错了什么? 预先感谢您的回复。
我找到答案了!
是关于QTextDocument的drawContents方法。 为了在文档中看到背景图像,您需要添加第二个参数。 它是一个 QRectF 对象,代表背景图像将被裁剪到的矩形的大小。
void QTextDocument::drawContents(QPainter *p, const QRectF &rect = QRectF()) Draws the content of the document with painter p, clipped to rect. If rect is a null rectangle (default) then the document is painted unclipped.
所以我做的是:
easuresDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print TextDocument of the Measures into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
averagesDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Averages into the document
pdfPrinter.newPage(); // We inject the current page and continue printing on new page
inOutDoc.drawContents(&painter, pdfPrinter.paperRect()); // We print the TextDocument of the Inputs/Outputs into the document
pdfPrinter.paperRect是没有边距的页面矩形。
此外,如果您希望背景图像按比例打印而不重复,则需要将打印机设置为 QPrinter::PrinterResolution
QPrinter pdfPrinter(QPrinter::PrinterResolution);