【问题标题】:Saving a QGraphicsScene to Svg changes scaling将 QGraphicsScene 保存到 Svg 会更改缩放
【发布时间】:2015-12-09 16:30:47
【问题描述】:

我需要将我的 QGraphicsScene 中的项目保存到 svg,并能够将该 svg 加载回现场。
我能做到...
但是每次将画布保存到 svg 时,加载时项目都会变大(反复保存和加载相同的 svg 会导致其增长)。
我找不到原因。

我附上一个示例代码 - 以及结果。

test1.pro

QT       += gui svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets core
TARGET = test1
TEMPLATE = app
SOURCES += \
    svggenerator.cpp

svggenerator.cpp

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
#include <QGraphicsSvgItem>
#include <QSvgGenerator>
#include <QSvgRenderer>
#include <QFile>
#include <QByteArray>
#include <QMessageBox>

void saveSceneToSvg(QGraphicsScene* s, const QString &filename) {
    QRectF newSceneRect;
    QGraphicsScene *tempScene = new QGraphicsScene(s->sceneRect());
    tempScene->setBackgroundBrush(QBrush(Qt::transparent));
    tempScene->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
    foreach(QGraphicsItem* item, s->items()) {
        newSceneRect |= item->mapToScene(item->boundingRect()).boundingRect();
        tempScene->addItem(item);
    }
    tempScene->setSceneRect(newSceneRect);
    tempScene->clearSelection();
    QSize sceneSize = newSceneRect.size().toSize();

    QSvgGenerator generator;
    generator.setFileName(filename);
    generator.setSize(sceneSize);
    generator.setViewBox(QRect(0, 0, sceneSize.width(), sceneSize.height()));
    generator.setDescription(QObject::tr("My canvas exported to Svg"));
    generator.setTitle(filename);
    QPainter painter;
    painter.begin(&generator);
    tempScene->render(&painter);
    painter.end();

    tempScene->clear();
    delete tempScene;
}

void loadSvg(QGraphicsScene* s, const QString &filename, const QPointF& p) {
    QGraphicsSvgItem* item = new QGraphicsSvgItem();
    QFile file(filename);
    file.open(QFile::ReadOnly);
    QByteArray contents = file.readAll();
    item->setSharedRenderer(new QSvgRenderer(contents));
    file.close();
    item->setPos(p);
    s->addItem(item);
}

void processScene(QGraphicsScene* s) {
    QGraphicsEllipseItem* eli = new QGraphicsEllipseItem();
    eli->setRect(QRectF(0, 0, 100, 100));
    eli->setPen(Qt::NoPen);
    eli->setBrush(Qt::red);
    eli->setPos(100, 300);
    s->addItem(eli);

    QGraphicsEllipseItem* eli1 = new QGraphicsEllipseItem();
    eli1->setRect(QRectF(0, 0, 100, 100));
    eli1->setPen(Qt::NoPen);
    eli1->setBrush(Qt::yellow);
    eli1->setPos(150, 300);
    s->addItem(eli1);

    QMessageBox::information(NULL, "hi", "click");

    saveSceneToSvg(s, "abcd.svg");
    loadSvg(s, "abcd.svg", QPointF(100,300));

    QMessageBox::information(NULL, "hi", "click");

    saveSceneToSvg(s, "abcd1.svg"); // saved with a dif name so I can see
    loadSvg(s, "abcd1.svg", QPointF(100,300));

    QMessageBox::information(NULL, "hi", "click");

    saveSceneToSvg(s, "abcd2.svg");
    loadSvg(s, "abcd2.svg", QPointF(100,300));

    // .... each time i call them they grow larger
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QGraphicsScene s;
    s.setSceneRect(50, 0, 1000, 800);
    QGraphicsView view(&s);
    view.show();
    processScene(&s);
    return app.exec();
}

结果:

查看 svg 本身,我可以看到 svg 的大小增加了大约 1.25...我无法解释,也无法确定其他示例是否如此。 (好像)

是什么导致了这种增长?我怎样才能阻止它?

(我也注意到顺序不同......我刚刚注意到这是一个不同的问题......但因为在我的“真实”代码中,我也有 z 顺序,我不在乎。)

我认为保存很好 - 生成的 svg 具有预期大小的大小和视图框。

加载其他 svg 很好 - 从外部源保存 svg 会创建一个大小相似的 svg。

问题似乎是当我加载由 svg 生成器创建的 svg 时,它的大小会增加。

(如果我可以确定总是这样的话,我可以尝试在负载时缩小它,但每次的比率并不完全是 1.25,虽然很接近......而且我不知道如何区分一个外部 svg 和一个生成的)。

【问题讨论】:

  • 只是猜测..会不会和你的scenRect s.setSceneRect(50, 0, 1000, 800);有关?能不能改一下,看看比例有没有变化?
  • @AlexanderTyapkov - 它没有。我玩过它以使我的示例更漂亮:-) 但我在“真实”程序中经历了同样的事情,具有完全不同的对象类型和大小。加载其他 svg 也很好。唯一不好的是加载自生成的 svg。
  • 好的。我现在会尝试重现该错误

标签: qt svg qgraphicsscene


【解决方案1】:

它看起来像一个 SvgGenerator 的错误。您提供给 SVG 生成器的大小仅用于形成 svg 的标题。 .svg 文件的实际大小与标题中写入的大小不同。我发现的唯一解决方法是在保存时将大小简单地减少 25%,类似于:

int width = qCeil(qreal(sceneSize.width()/1.25));
int height = qCeil(qreal(sceneSize.height()/1.25));

generator.setSize(QSize(width, height));
generator.setViewBox(QRect(0, 0, width, height));

【讨论】:

  • 谢谢...我希望有更好(更准确)的方法。如果我保存一个大小为 100x100 的项目并乘以 0.8,我得到一个大小为 99x99 的 svg。我必须创建 svg 然后编辑文件....
  • 同样在 Qt4 中,每次我加载保存的 svg 时,所有项目 - 以及 svg 本身 - 都会出现黑色中风。
  • 您在乘以 0.8 后忘记了 qCeil。如果你会这样做,那么所有 svg 的大小将是 100 x 100。可能它也将解决中风的错误。我使用的是 qt.5.5 并且在输出图像上没有看到任何笔画。
  • Qt5没有笔画,只有Qt4。如果将保存的 svg 加载到场景中,则会出现笔画,然后将场景再次保存为 svg。中风的原因是它对插入每个实体之前的“默认值”的解释 - 删除那些(手动)修复问题。我使用 4.7.4(和 5.5)。
  • 在 Qt 5.5 上添加 int width = qCeil(sceneSize.width()*0.8);更改 svg 文件的最终大小。你是用同样的方法做的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2020-01-21
相关资源
最近更新 更多