使用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

回到顶部