问题
I need to save the items from my QGraphicsScene
to an svg, and be able to load that svg back on the scene.
I can do it...
But each time the canvas is saved to svg, upon load the items are somewhat bigger (and repeatedly saving and loading the same svg causes it to grow).
I can't find the cause.
I am attaching a sample code - and the result.
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();
}
Result:
Looking at the svgs themselves, I can see that the svgs increase in size by approx 1.25... I can't explain, and can't be sure this will be true for other examples. (it seems to)
What is causing this growth ? How can I stop it ?
(Also I notice the ordering is different ... I just noticed and that is a different problem... But since in my "real" code I also have z order I don't care.)
Saving I think is fine - the resulting svg has size and view box of expected size.
Loading other svgs is fine - saving an svg from outside source creates an svg similar in size.
It seems the problem is when I am loading an svg created by the svg generator that it increases in size.
(If I could be sure it is always the case I could try scaling it down on load, but the ratio is not exactly 1.25 each time, close though... and I don't know how to tell the difference between an outside svg and a generated one).
回答1:
It looks like a bug of SvgGenerator. The size which you provide to SVG generator is used only to form the header of svg. The actual size of .svg file differs from one written in the header. The only workaround I found is simple 25 percent decrease of size on save similar to:
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));
来源:https://stackoverflow.com/questions/34183996/saving-a-qgraphicsscene-to-svg-changes-scaling