c++ - 使用 Qt QPainter 和 QSvgGenerator 创建的 SVG 裁剪到视口(viewport)大小

标签 c++ qt svg qt5 qpainter

对于一个项目,我使用 QPainter 和 QSvgGenerator 来创建 SVG 作为输出。该项目基本上从 C++ 代码生成基本类图。但是,当我使用 Google Chrome 或任何其他网络浏览器打开 SVG 时,它会根据浏览器窗口的大小进行裁剪,没有任何滚动条。在调整窗口大小时,会发生进一步的裁剪。

相关代码

QSvgGenerator temp_img; 
//Save file as image
QString path = QFileDialog::getSaveFileName(w, ("Save as image"), "", 
("SVG file (*.svg)"));

if (path.isEmpty())
    return;

temp_img.setFileName(path);

QPainter painter;
painter.begin(&temp_img);
painter.setFont(QFont("Arial",12));
.
.
.
painter.end();

我试过使用 setViewBox() 但没有效果。 我是第一次使用 Qt,所以请尽量详细。由于质量问题,我更喜欢 SVG 而不是位图。

编辑:缩小显示隐藏的部分。

最佳答案

由于 OP 没有提供 MCVE ,我自己准备了一个:

#include <QtWidgets>
#include <QtSvg/QSvgGenerator>

const int w = 100, h = 100;

void renderTest(QPainter &qPainter, double s)
{
  qPainter.setTransform(QTransform().scale(s, s));
  qPainter.setFont(QFont("Arial", 12));
  qPainter.setPen(Qt::gray);
  qPainter.drawRect(0, 0, w, h);
  qPainter.setPen(Qt::black);
  qPainter.drawLine(0.1 * w, 0.5 * h, 0.9 * w, 0.5 * h);
  qPainter.drawLine(0.5 * w, 0.1 * h, 0.5 * w, 0.9 * h);
  qPainter.drawLine(0.45 * w, 0.2 * h, 0.55 * w, 0.2 * h);
  qPainter.drawLine(0.45 * w, 0.8 * h, 0.55 * w, 0.8 * h);
  qPainter.drawLine(0.2 * w, 0.45 * h, 0.2 * w, 0.55 * h);
  qPainter.drawLine(0.8 * w, 0.45 * h, 0.8 * w, 0.55 * h);
  qPainter.drawText(QPointF(0.51 * w, 0.49 * h), "0");
  qPainter.drawText(QPointF(0.51 * w, 0.79 * h), "-1");
  qPainter.drawText(QPointF(0.51 * w, 0.19 * h), "+1");
  qPainter.drawText(QPointF(0.21 * w, 0.49 * h), "-1");
  qPainter.drawText(QPointF(0.81 * w, 0.49 * h), "+1");
  qPainter.setPen(Qt::blue);
  qPainter.drawEllipse(QPointF(0.5 * w, 0.5 * h), 0.3 * w, 0.3 * h);
}

void renderSvgFile(const QString &qFilePath, double s)
{
  QSvgGenerator qSvgGen;
  qSvgGen.setFileName(qFilePath);
  qSvgGen.setSize(QSize(s * w, s * h));
  renderTest(QPainter(&qSvgGen), s);
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // render tests
  for (int i = 1; i <= 100; i *= 10) {
    const QString qFilePath = QString("testQSvgGen.%1%2.svg").arg(i).arg("0%");
    qDebug() << "Render" << qFilePath;
    renderSvgFile(qFilePath, i * 0.1);
  }
  // done
  return 0;
}

它生成三个文件:

  • testQSvgGen.10%.svg
  • testQSvgGen.100%.svg
  • testQSvgGen.1000%.svg

Preview in Windows Explorer (with SVG-Preview plug-in)

虽然图片大小不一,但预览没有明显区别。原因是预览将结果缩放到它自己所需的分辨率以使输出适合当前资源管理器图标大小。 (同样适用于右侧尺寸的预览尺寸。)

View in Google Chrome Browser

与此相反,Web 浏览器(上面快照中的 Google Chrome)会考虑 SVG 的大小设置。

这些设置是

  • testQSvgGen.10%.svg :
<svg width="3.52778mm" height="3.52778mm"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
 version="1.2" baseProfile="tiny">
  • testQSvgGen.100%.svg
<svg width="35.2778mm" height="35.2778mm"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
 version="1.2" baseProfile="tiny">
  • testQSvgGen.100%.svg
<svg width="352.778mm" height="352.778mm"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
 version="1.2" baseProfile="tiny">

仔细查看生成的 SVG 代码后发现,这 3 个文件总体上看起来非常相似。我强制缩放

  qPainter.setTransform(QTransform().scale(s, s));

将图形输出调整为预期的图像大小简单地转换为 transform="matrix()"具有每个组缩放比例的属性 ( <g> )。


所以,我无法确认 OP 提示了什么:

尺寸设置在QSvgGenerator::setSize()在生成的 SVG 文件中被考虑在内,并且浏览器尊重此设置(如预期的那样)。


生成的源代码testQSvgGen.10%.svg :

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="352.778mm" height="352.778mm"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  version="1.2" baseProfile="tiny">
<title>Qt SVG Document</title>
<desc>Generated with Qt</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >

<g fill="none" stroke="#a0a0a4" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<rect x="0" y="0" width="100" height="100"/>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<polyline fill="none" vector-effect="none" points="10,50 90,50 " />
<polyline fill="none" vector-effect="none" points="50,10 50,90 " />
<polyline fill="none" vector-effect="none" points="45,20 55,20 " />
<polyline fill="none" vector-effect="none" points="45,80 55,80 " />
<polyline fill="none" vector-effect="none" points="20,45 20,55 " />
<polyline fill="none" vector-effect="none" points="80,45 80,55 " />
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="51" y="49" font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
 >0</text>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="51" y="79" font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
 >-1</text>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="51" y="19" font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
 >+1</text>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="21" y="49" font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
 >-1</text>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="81" y="49" font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
 >+1</text>
</g>

<g fill="none" stroke="#0000ff" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal" 
>
<circle cx="50" cy="50" r="30"/>
</g>
</g>
</svg>

关于c++ - 使用 Qt QPainter 和 QSvgGenerator 创建的 SVG 裁剪到视口(viewport)大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57055080/

相关文章:

c++ - 如何定义可以继承的模板特定类型?

javascript - 将 'rect' 元素添加到 d3 中的空白 svg Canvas 在 .data() 上失败

reactjs - 在 react 应用程序中渲染 svg 图像时延迟

javascript - 动态更改 SVG 元素后对其进行动画处理

c++ - 使模板接受特定的类/类族?

c++ - 有 char[1] 和偏移量如何读取 int?

c++ - 在 xml 中存储 C++ 二进制输出

c - 将主要参数传递给 gui 库的 init 函数

python - 使用 PyQt 捕获网络摄像头视频

c++ - 使用 QDoubleSpinBox 自然地键入十进制值