如何打印包含文本和图形的QGraphicsScene?

4
我有一个QGraphicsScene,上面绘制了图形和文本。当我尝试打印时,图形很好,但文本使用的是以点为单位定义的字体大小,因此当我将其传递给使用QPrinter初始化的QPainterscene->render()函数时,文本非常大。
我应该如何打印带有文本的QGraphicsScene
编辑:
这是我的当前打印代码,其中scene_是我的QGraphicsScene自定义子类:
  QPrinter printer(QPrinter::HighResolution);
  QPrintDialog dialog(&printer, this);
  dialog.exec();
  std::cout << printer.resolution() << std::endl;
  QPainter painter(&printer);
  scene_->render(&painter);

std::cout这一行似乎没有任何效果。打印机仍然认为文本很大,因此每个文本项只打印第一个字母的一小部分。

2个回答

3
根据QPrinter文档,为了使文本和图形匹配,您需要以像素为单位指定字体大小。请注意,QFont有一个setPixelSize方法。

这会使字体依赖于设备。我的用户可能有多个显示器,我不想为一个显示器计算像素大小的字体,然后他们将其拖到另一个显示器上,结果看起来很糟糕。 - David Burson
我需要正常使用点大小,但当用户打印时,遍历所有文本并重新计算像素中的字体吗?希望有更好的方法。 - David Burson
@David Burson:这将必然是与设备相关的,才能在显示器和打印机上同时使用。设置一个点大小并使其与设备无关意味着,无论是在纸张上还是在分辨率不同的监视器上,72点文字始终都是一英寸高的。因此,是的,我认为您必须将打印机视为特殊情况,并计算出像素大小。 - Troubadour
这样做是有道理的,但是有没有更好的处理打印的方法,而不是迭代每个文本对象,重置其字体为计算出的像素大小,将场景渲染到打印机上,然后再迭代所有文本对象并将它们的字体重置回适当的点大小? - David Burson
@David Burson:你可以将代码放在重新实现文本对象的paint函数中。查询绘图器的device(),如果它动态转换为QPrinter,则使用像素大小。或者,如果您的图形和文本非常紧密地依赖于彼此的大小,则最好在所有地方使用像素大小。 - Troubadour
像素大小似乎是最好的选择,现在对我们来说已经起作用了。 - David Burson

1

设置 QPrinter:

默认情况下,QPrinter 对象会初始化为屏幕分辨率(通常为 96 DPI),除非您在构造函数中指定 QPrinter::HighResolution,这将使用打印机的分辨率。

如果您正在使用 QPrintDialog 设置 QPrinter 对象,则代码应该如下:

QPrinter printer(QPrinter::HighResolution);
QPrintDialog dialog(&printer, this);
dialog.exec();
std::cout << printer.resolution() << std::endl;

接下来,程序应该输出所选打印机的DPI。在我的情况下,它打印出600。

如果您没有使用QPrintDialog,则应该像上面显示的那样使用QPrinter构造函数,然后调用setResolution(DPI)并知道您打印机的DPI。

这应该会导致正确呈现的字体。

更新:

现在周末到了,我终于有时间认真考虑这个问题 :) 虽然对于设置QPrinter来说技术上是正确的,但上述解决方案对于包含以点大小指定的文本的图形场景来说并不实用。由于所有图形项都是以像素坐标指定的,因此只有将字体大小也以像素为单位指定才有意义,以确保在与其他图形基元混合时字体看起来正好如预期。

不必担心不同监视器上文本的大小,因为图形项本身不是分辨率独立的。视图可以指定比例缩放以处理不同分辨率和DPI监视器。

在打印时,默认情况下,QPrinter会缩放以适应整个场景到页面。这是有道理的,因为在600 DPI打印机上的100 x 100正方形将在您的纸张上宽1/6英寸 :)


我想使用QPrintDialog。我尝试了你的解决方案,但没有效果 - 我是C++和Qt的新手,可能错过了什么。我还添加了#include <iostream>以使std::cout编译。我的完整打印代码现在已添加到我的原始问题中 - 有什么想法吗? - David Burson
cout只是为了让您看到QPrinter是否从QPrintDialog中选择了正确的DPI设置。在对话框上单击“打印”后,它会打印出什么?(您应该从控制台运行程序,以便在IDE不显示输出时可以看到它。) - Arnold Spence
打印机分辨率为 600。 - David Burson
听起来没问题。我今晚会做一些实验,看看得到什么结果。我会分享我收集到的所有信息,但可能不如你需要及时。 :) - Arnold Spence
谢谢 - 我非常感激!顺便说一下,如果有所不同的话,我的场景上的文本对象是QGraphicsObject的自定义子类,其中(除其他外)重新实现了paint函数以允许沿曲线绘制文本。我想提一下这一点,以防文本在场景中的呈现方式有所不同。 - David Burson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接