使用Qt
无法生成具有可接受输出质量的PDF我试图在Windows下使用Qt5生成pdf。我的文档包含文本,图像和图表。由于我熟悉Qt和Qwt,我相信最好的策略是创建一个带有我的文档布局的QWidget
,并将其打印出来。但是我面临的问题并不能以可接受的结果结束。使用Qt
这是我的MCVE,用一个简单的页的文件:
- 基于Qt document并用标题和图像
- 一块文本
- 的简单图表
的报头How can I print a QWidget in Qt?,我结束了这段代码:
main.cpp中:
#include <QApplication> #include <QIcon>
#include <QDesktopServices>
#include <QWidget>
#include <QPrinter>
#include <QPainter>
#include <QPagedPaintDevice>
#include <QUrl>
#include "ui_report.h"
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_plot_canvas.h"
#include "qwt_point_data.h"
#include "qwt_legend.h"
#include <sstream>
#include <memory>
bool printWidget(QWidget& widget, bool highResolution, const std::string& fileName)
{
QPrinter printer(highResolution ? QPrinter::HighResolution : QPrinter::ScreenResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOrientation(QPrinter::Portrait);
printer.setPaperSize(QPrinter::A4);
printer.setPageMargins(15,15,15,15,QPrinter::Millimeter);
printer.setFullPage(true);
printer.setOutputFileName(fromSDEString(fileName.c_str()));
QPainter painter(&printer);
double xscale = printer.pageRect().width()/double(widget.width());
double yscale = printer.pageRect().height()/double(widget.height());
double scale = qMin(xscale, yscale);
painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
printer.paperRect().y() + printer.pageRect().height()/2);
painter.scale(scale, scale);
painter.translate(-widget.width()/2, -widget.height()/2);
widget.render(&painter, QPoint(), QRegion(), QWidget::DrawChildren);
return painter.end();
}
bool generateReport(bool drawWithPrinterResolution, bool printHighResolution, const std::string& fileName)
{
QWidget widget;
Ui::Report ui;
ui.setupUi(&widget);
if (drawWithPrinterResolution)
{
QPrinter printer(printHighResolution ? QPrinter::HighResolution : QPrinter::ScreenResolution);
printer.setOrientation(QPrinter::Portrait);
printer.setPaperSize(QPrinter::A4);
printer.setPageMargins(15,15,15,15,QPrinter::Millimeter);
printer.setFullPage(true);
// force printer page size to be used:
QSize pageSize = printer.pageRect().size();
widget.resize(pageSize);
}
ui.header->setFrameShape(QFrame::Shape::Box);
QHBoxLayout* headerLayout = new QHBoxLayout(ui.header);
QLabel* icon = new QLabel(ui.header);
QSize size = ui.header->size();
icon->setPixmap(QPixmap(":/gui_test/mainframe.png").scaledToHeight(size.height()));
headerLayout->addWidget(icon);
headerLayout->addWidget(new QLabel("Document title",ui.header));
headerLayout->setStretch(0, 0);
headerLayout->setStretch(1, 1);
ui.inputs->setText("<b>Info</b>: Information");
QwtPlot* plot = new QwtPlot(&widget);
QwtPlotCurve* curve = new QwtPlotCurve("Plots");
curve->setStyle(QwtPlotCurve::Lines);
QVector<QPointF> samples;
for (size_t i = 0; i != 100; ++i)
{
samples.push_back(QPointF(i,20*i+10));
}
curve->setData(new QwtPointSeriesData(samples));
curve->attach(plot);
plot->setTitle("Result");
plot->setAxisScale(QwtPlot::xBottom, samples.front().rx(), samples.back().rx());
plot->replot();
ui.graphLayout->addWidget(plot);
if (printWidget(widget, printHighResolution, fileName))
{
QDesktopServices::openUrl(QUrl::fromLocalFile(fileName.c_str()));
return true;
}
else
{
return false;
}
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
app.setWindowIcon(QIcon(":/gui_test/mainframe.png"));
generateReport(false, false, "report_small_widget_to_screen.pdf");
generateReport(false, true, "report_small_widget_to_high.pdf");
generateReport(true, false, "report_big_widget_to_screen.pdf");
generateReport(true, true, "report_big_widget_to_high.pdf");
return 0;
}
report.ui:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0">
<class>Report</class>
<widget class="QWidget" name="Report">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>525</width>
<height>742</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,100,0">
<item>
<widget class="QFrame" name="header"/>
</item>
<item>
<widget class="QLabel" name="inputs">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="graphLayout"/>
</item>
<item>
<widget class="QWidget" name="footer" native="true"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
mainframe.png:的256×256像素A Qt的图标:/wp-content/uploads/new2022/20220327voicc/58150951.png。
正如你可以看到,这会产生4个文件:
- report_small_widget_to_screen.pdf:其中插件与来自UI文件(252x742)小A4比创建,然后印有
QPrinter::ScreenResolution
- report_small_widget_to_high.pdf :在哪里插件与来自UI文件(252x742)小A4比创建,然后印有
QPrinter::HighResolution
- report_big_widget_to_screen.pdf:其中插件被缩放到打印机的页大小(793x1123),然后印有
QPrinter::ScreenResolution
- report_big_widget_to_high.pdf:当小部件扩展到打印机的页面大小(9917x14033),然后印有
QPrinter::HighResolution
没有给我一个可以接受的结果:
- report_small_widget_to_screen.pdf:文本,Qt的图标QWT图是像素化
- report_small_widget_to_high.pdf:文字是确定的,但Qt的图标和QWT图是像素化
- report_big_widget_to_screen.pdf:文本,Qt的图标和QWT图是像素化
- report_big_widget_to_high.pdf:文本,Qt图标和Qwt图表非常小,几乎不可读。但现在Qwt的情节不再像素化了
我应该改变什么来获得一个不错的输出?
- 使用高分辨率(非像素化)绘制的文本与report_small_widget_to_high中一样。PDF
- 随着图标具有高分辨率(未像素化)正在制定
- 随着图被描绘具有高分辨率(未像素化)
report_small_widget_to_screen.pdf样子(一切都是像素化) :
report_small_widget_to_high.pdf外观像(只有文字没有像素化):
report_big_widget_to_high.pdf样子(一切都太小):
注:我只是跑相同的测试与更大的.ui资源(2100x2970),然后图像分辨率看起来更好,但文字显示非常小。我想知道QWidget打印在这里是合适的解决方案,因为它看起来像文本大小取决于用户界面大小,所以你无法控制文本的大小(就像你在像Word这样的文档中使用字体大小......) )
回答:
就我个人而言,我会强烈建议将内容创建为QTextDocument,然后将其打印出来。你可以(IIRC,有一段时间没有使用QwtPlot)将图表渲染成图像。然后很容易add the image到任何你想要的文件。当然,和你的静态图像一样。您可以在文档中使用HTML/CSS(尽管类名称中包含“文本”)以及许多其他选项。
实例添加要求:
这将是非常简单的,并没有完全形成,但希望它可以帮助...
QTextDocument qtdoc; // start with a QTextDocument // prepare standard html with embedded image
QString html = "<html><body>" \
"<h1>Hello World!</h1>" \
"<img src='mydata://myimg.png' border='0' />" \
"</body></html>";
QImage image = getChartImage(); // theoretical function
// here we add the actual image data to the document
qtdoc.addResource(QTextDocument::ImageResource, QUrl("mydata://myimg.png"), image);
qtdoc.setHtml(html);
// document is now fully formed and ready for display/print
打印到PDF或HTML文件:
void printToFile(const QTextDocument & qtdoc) {
QString fn = QFileDialog::getSaveFileName(this, tr("Select output file"), QString(), tr("PDF Files(*.pdf);;HTML-Files (*.htm *.html)"));
if (fn.isEmpty())
return;
if (fn.endsWith(".pdf", Qt::CaseInsensitive)) {
QPrinter printer;
printer.setPageMargins(10.0,10.0,10.0,10.0,printer.Millimeter);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setColorMode(QPrinter::Color);
printer.setOutputFileName(fn);
qtdoc.print(&printer);
}
else { // HTML
QTextDocumentWriter writer(fn);
writer.write(qtdoc);
}
}
输出到打印机:
void print(const QTextDocument & qtdoc) {
QPrinter printer;
printer.setPageMargins(10.0,10.0,10.0,10.0,printer.Millimeter);
QPrintDialog *dialog = new QPrintDialog(&printer, this);
dialog->setWindowTitle(tr("Print Document"));
if (dialog->exec() != QDialog::Accepted)
return;
qtdoc.print(&printer);
}
的工作版本的实际截图(它的代码开始here,但有点烦琐的遵循):
和PDF导出:http://max.wdg.us/docs/so/SO-47879329.pdf
以上是 使用Qt 的全部内容, 来源链接: utcz.com/qa/264080.html