我正在将一些Qt(C++和QML)代码从Qt4.8升级到Qt5.1。
Qt4.8代码是一个琐碎的C++"QML查看器"应用程序,它将QDeclarativeView
和一堆QML子类化。
将其更改为使用Qt5/QtQuick2的QQuickView
非常容易,除了一件事:
Qt4.8应用程序有一种打印成PDF的方法:
void MyQMLViewer::printToPDF(const QString& filename) const {
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setPageSize(QPrinter::A3);
printer.setOutputFileName(filename);
printer.setOrientation(QPrinter::Landscape);
QPainter painter(&printer);
render(&painter);
}
Qt5.1需要一些"环境"更改才能获得QPrinter
(即将QT += printsupport
添加到project.pro文件和#include <QtPrintSupport>
),但似乎还有一个更根本的问题,即QQuickView
没有提供任何明显与QPrinter
的QGraphicsView
/QPainter
/QPaintDevice
世界兼容的东西(具体地说,QQuickView
没有render
方法,它所拥有的所有绘图/绘画/渲染相关方法似乎都与OpenGL紧密相连)。
关于如何最好地从QQuickView
获得高质量的PDF输出,有什么建议吗?
(请注意,我是not
,只是想截屏视图;使用QDeclarativeView
,上面的代码生成的PDF具有更好的分辨率,甚至比在我最大的显示器上全屏显示的应用程序更好)。
我看到"将QML应用程序移植到Qt 5"指南的"QDeclarativeItem和QDeclaractiveView"部分确实提到了QGraphicsView
特定功能的损失,但没有提供任何解决方案(尽管它确实提到了在新制度中购买具有自定义QPainter
渲染的项目的情况下的工作循环)。
用一些额外的背景信息更新:可以在这里找到使用上述代码从QDeclarativeView打印的PDF示例。这里有一个大小适中的显示器上的相同视图的png。(这实际上是一系列幻灯片中的最后一张;它实际上是前几张幻灯片的库,可以将每张幻灯片反弹到屏幕上;如果我有时间的话,我会研究库是唯一的,并将每张分散的幻灯片转换为Prezi风格演示的视图的可行性;不过,怀疑QDeclarative的性能还不够,这也是或者想要进入QtQuick2+Qt5.2的新场景图内容)。无论如何,如果你把PDF放大到100%,你会看到文本是……嗯,我认为这比一个合理大小的图像文件所能管理的任何东西都要好,尽管倾斜的文本基线看起来可能有点不均匀。还有一个问题是PDF中没有表示不透明度值(因此阴影和"气泡"显示为实心);我尝试QtQuick2版本的另一个动机实际上是看看半透明元素是否得到了更好的处理。我认为PDF只包含所有元素的光栅化(或者可能是矢量轮廓),因为像"pdftotext"这样的实用程序无法从中提取任何内容。我对PDF工具的了解不够,不知道如何检查事物的内部结构,但我认为那里有一些层次结构,QML元素树都是使用与QML类似的嵌套转换结构来布局的。只是为了进行比较和我可能会努力实现的丰富性,这里有一张我与LaTeX/Beamerposter合作的海报;我发现Beamerposter的刚性块结构与QML似乎提供的可能性相比相当有限(而且很麻烦)。顺便说一句,我的愿望清单/待办事项列表中的另一件事是QML元素,它可以呈现LaTeX源代码、数学和所有内容,只是为了两全其美。
更新:最近关于Qt5.8中所有后端更改的Qt博客文章中有一条评论链接到此Qt问题,以使用QPainter渲染的QtQuick场景来渲染PDF的新可能性。
目前,Qt中没有支持将场景图渲染为pdf的代码。用于渲染Qt Quick 2的基础数据保存在场景图中。正如Laszlo所建议的,您需要迭代场景图并生成PDF基元。这里有一些阻抗不匹配,但这应该是可行的。我认为概念验证可能足够小,可以放在这里,所以我会看看它有多容易:)
如果你真的想要一个PDF,你目前别无选择,只能将其渲染成300dpi的大图像,并将其包裹在PDF中。如果海报有大面积的纯色,则图像不必很大。PDF可以做TIFF编码,也可以做JPEG编码。