Евгений Легоцкой1 апреля 2016 г. 12:51

Qt/C++ - Урок 045. SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene

В прошлой статье был рассмотрен пример того, как сохранить объекты графической сцены в файл SVG, а потом мы смогли открыть его в CorelDraw. А теперь попробуем этот же самый файл открыть и восстановить графические объекты в QGraphicsScene .

Отмечу, что мы не будем использовать класс QSvgRenderer для этого по той причине, что он без проблем поместит содержимое файла SVG на графическую сцену, НО это будет один единый графический объект, а если Вам нужно, чтобы он восстановился в качестве отдельных графических объектов, например, QGraphicsItem , то необходимо будет парсить файл SVG изготавливать из него все графические объекты.

Поскольку файл SVG имеет структуру XML-формата, то разобрать его не представит никакого труда с помощью классов семейства QDomDocument.

Структура проекта

В качестве примера, будет использоваться проект из предыдущей статьи, но будет разбавлен дополнительным классом с двумя статическими методами.

  • SVGExample.pro - профайл проекта;
  • svgreader.h - заголовочный файл парсера SVG;
  • svgreader.cpp - файл исходных кодов парсера SVG;
  • mainwindow.h - заголовочный файл главного окна приложения;
  • mainwindow.cpp - файл исходных кодов главного окна приложения;
  • mainwindow.ui - файл формы главного окна приложения;
  • main.cpp - стартовый файл исходных кодов приложения.

Структура SVG файла

Поскольку нам потребуется парсить данный файл, то заглянем в его внутренности.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="141.111mm" height="141.111mm"
 viewBox="0 0 400 400"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  version="1.2" baseProfile="tiny">
<title>SVG Example</title>
<desc>File created by SVG Example</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >

<g fill="#ff0000" fill-opacity="1" stroke="#000000" stroke-opacity="1" stroke-width="2" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal" 
>
<rect x="10" y="50" width="100" height="50"/>
</g>
</g>

Итак, нас интересуют теги svg, g, rect. В теге svg содержатся размеры графической сцены - это viewBox. В теге rect содержатся размеры прямоугольника, а в теге g , в который обёрнут тег rect содержатся цвета заливки и абриса прямоугольника, а также толщина абриса. Их и нужно будет спарсить.

mainwindow.ui

В данном файле будет добавлена только кнопка load, по сигналу от которой откроем диалог выбора файла и запустим открытие нашего файла SVG.

SVGExample.pro

Обращаю ваше внимание на то, что в профайле проекта нужно будет подключить модуль xml.

QT += xml

svgreader.h

Ничем не примечательный заголовочный файл с парой статических методов в классе.

#ifndef SVGREADER_H
#define SVGREADER_H

#include <QList>
#include <QGraphicsRectItem>

class SvgReader
{
public:
    SvgReader();
    static QList<QGraphicsRectItem *> getElements(const QString filename);
    static QRectF getSizes(const QString filename);
};

#endif // SVGREADER_H

svgreader.cpp

А вот здесь и кроется вся магия. В двух выше приведённых методах будем получать список прямоугольников и размеры графической сцены.

#include "svgreader.h"
#include <QPen>
#include <QFile>
#include <QMessageBox>
#include <QDomDocument>
#include <QStringList>

SvgReader::SvgReader()
{

}

QList<QGraphicsRectItem *> SvgReader::getElements(const QString filename)
{
    QList<QGraphicsRectItem *> rectList;    // Объявим в стеке список прямоугольников

    QDomDocument doc;       // объект документа
    QFile file(filename);   // Открываем наш SVG-файл
    // Если он не открылся или не удалось передать содержимое в QDocDocument
    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return rectList;    // то возвратим список, но пустой

    // Ищем в документе все объекты с тегом g
    QDomNodeList gList = doc.elementsByTagName("g");
    // Начинаем их перебирать
    for (int i = 0; i < gList.size(); i++) {
        QDomNode gNode = gList.item(i);     // Выделяем из списка ноду
        QDomElement rectangle = gNode.firstChildElement("rect");    // И ищем в ней элемент c тегом rect
        // Если полученный элементы не нулевой, то
        if (rectangle.isNull()){
            continue;
        } else {
            // начинаем формировать прямоугольник
            QGraphicsRectItem *rect = new QGraphicsRectItem();
            // Этот флаг делает объект перемещаемым, потребуется для проверки
            rect->setFlag(QGraphicsItem::ItemIsMovable);
            // Забираем размеры из тега rect
            QDomElement gElement = gNode.toElement();
            rect->setRect(rectangle.attribute("x").toInt(),
                          rectangle.attribute("y").toInt(),
                          rectangle.attribute("width").toInt(),
                          rectangle.attribute("height").toInt());

            /* Забираем из элемента ноды gNode параметры цветов
             * да да да... именно из gNode, а не из rectangle. Эти параметры храняться в теге g
             * */
            QColor fillColor(gElement.attribute("fill", "#ffffff"));    // цвет заливки
            fillColor.setAlphaF(gElement.attribute("fill-opacity","0").toFloat());
            rect->setBrush(QBrush(fillColor));

            // а также цвет и толщина абриса
            QColor strokeColor(gElement.attribute("stroke", "#000000"));
            strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());

            rect->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
            rectList.append(rect);  // добавляем прямоугольник в список
        }
    }
    file.close();
    return rectList;
}

QRectF SvgReader::getSizes(const QString filename)
{
    QDomDocument doc;       // инициализируем в стеке объект QDomDocument
    QFile file(filename);   // Открываем наш SVG-файл
    // Если он не открылся или не удалось передать содержимое в QDocDocument
    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return QRectF(0,0,200,200); // то возвратим значения для сцены по умолчанию

    /* Далее забираем список элементов с тегом svg.
     * В случае, если список элементов будет не пустой,
     * то заберём размеры графической сцены.
     * */
    QDomNodeList list = doc.elementsByTagName("svg");
    if(list.length() > 0) {
        QDomElement svgElement = list.item(0).toElement();
        QStringList parameters = svgElement.attribute("viewBox").split(" ");
        return QRectF(parameters.at(0).toInt(),
                      parameters.at(1).toInt(),
                      parameters.at(2).toInt(),
                      parameters.at(3).toInt());
    }
    return QRectF(0,0,200,200);
}

mainwindow.h

Здесь добавился только слот для реакции на сигнал от кнопки открытия файла.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QSvgGenerator>
#include <QFileDialog>
#include <QPainter>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_saveButton_clicked();
    void on_loadButton_clicked();

private:
    Ui::MainWindow *ui;
    QGraphicsScene *scene;  // Графическая сцена
    QString path;           // Путь сохранения файла
};

#endif // MAINWINDOW_H

mainwindow.cpp

Приведу в этом файле только содержимое относящееся непосредственно к разбору SVG файла. В слоте обработки нажатия кнопки выбирается с помощью диалогового окна файл и разбирается на графические объекты.

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "svgreader.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    scene = new QGraphicsScene();
    ui->graphicsView->setScene(scene);
    scene->setSceneRect(0,0,400,400);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_saveButton_clicked()
{
    // Код из предыдущего урока по работе с SVG
}

void MainWindow::on_loadButton_clicked()
{
    QString newPath = QFileDialog::getOpenFileName(this, trUtf8("Open SVG"),
                                                   path, tr("SVG files (*.svg)"));
    if (newPath.isEmpty())
        return;

    path = newPath;
    scene->clear();

    scene->setSceneRect(SvgReader::getSizes(path)); // Зададим размеры графической сцены

    // Установим на графическую сцену объекты, получив их с помощью метода getElements
    foreach (QGraphicsRectItem *item, SvgReader::getElements(path)) {
        QGraphicsRectItem *rect = item;
        scene->addItem(rect);
    }
}

Итог

В результате вы сможете разобрать сохранённый Вами SVG файл, чтобы забрать из него хотя бы прямоугольники. Если вы хотите забирать и все остальные объекты, то придётся изрядно попотеть и написать парсер для все этих остальных объектов по аналогии с прямоугольником. Единственное, что хочу отметить, не пытайтесь с помощью этого кода открыть файл, созданный изначально в CorelDraw, дело в том, что версии структуры файла SVG тоже сильно отличаются. И данный код предназначен для парсинга файла, который был создан в прошлом уроке, а структура генерируемых файлов пакетом CorelDraw несколько отличается и не будет прочитана полностью.

Подробнее вы можете с этим ознакомиться в видеоуроке. А проект, объединивший оба урока скачать по ссылке: SvgExample

  1. Сохранение объектов QGraphicsScene в файл векторной графики SVG

Видеоурок

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Поддержать автора Donate
F
  • #
  • 12 августа 2017 г. 8:24

Здравствуйте!

Назрел вопрос насчет данной темы.
Реализовал отрисовку и перемещение объектов на сцене по структуре урока https://evileg.com/post/86/
Но там я в MoveItem.cpp отрисовывал не с drawRect, а с drawEllipse
void MoveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->setPen(Qt::black);
    painter->setBrush(Qt::cyan);
    //painter->drawRect(-30,-30,60,60);
    painter->drawEllipse(-30,-30,30,30);
    painter->drawEllipse(-25,-25,20,20);
    painter->drawEllipse(-20,-20,10,10);
    Q_UNUSED(option);
    Q_UNUSED(widget);
}
Далее возвращал область также прямоугольную
QRectF MoveItem::boundingRect() const
{
    return QRectF (-30,-30,30,30);
}
После добавления нескольких объектов на сцену
также проделал процесс сохранения в *.svg. При этом создался файл, где тег rect отсутствует
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="176.389mm" height="176.389mm"
viewBox="0 0 500 500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  version="1.2" baseProfile="tiny">
<title>SVG VKR</title>
<desc>File created by Fidan Gallyamov</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,416,71)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="#00ffff" fill-opacity="1" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,416,71)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,-15 C0,-6.71573 -6.71573,0 -15,0 C-23.2843,0 -30,-6.71573 -30,-15 C-30,-23.2843 -23.2843,-30 -15,-30 C-6.71573,-30 0,-23.2843 0,-15 "/>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M-5,-15 C-5,-9.47715 -9.47715,-5 -15,-5 C-20.5228,-5 -25,-9.47715 -25,-15 C-25,-20.5228 -20.5228,-25 -15,-25 C-9.47715,-25 -5,-20.5228 -5,-15 "/>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M-10,-15 C-10,-12.2386 -12.2386,-10 -15,-10 C-17.7614,-10 -20,-12.2386 -20,-15 C-20,-17.7614 -17.7614,-20 -15,-20 C-12.2386,-20 -10,-17.7614 -10,-15 "/>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,416,71)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,70,190)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="#00ffff" fill-opacity="1" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,70,190)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,-15 C0,-6.71573 -6.71573,0 -15,0 C-23.2843,0 -30,-6.71573 -30,-15 C-30,-23.2843 -23.2843,-30 -15,-30 C-6.71573,-30 0,-23.2843 0,-15 "/>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M-5,-15 C-5,-9.47715 -9.47715,-5 -15,-5 C-20.5228,-5 -25,-9.47715 -25,-15 C-25,-20.5228 -20.5228,-25 -15,-25 C-9.47715,-25 -5,-20.5228 -5,-15 "/>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M-10,-15 C-10,-12.2386 -12.2386,-10 -15,-10 C-17.7614,-10 -20,-12.2386 -20,-15 C-20,-17.7614 -17.7614,-20 -15,-20 C-12.2386,-20 -10,-17.7614 -10,-15 "/>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,70,190)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,319,236)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="#00ffff" fill-opacity="1" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,319,236)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M0,-15 C0,-6.71573 -6.71573,0 -15,0 C-23.2843,0 -30,-6.71573 -30,-15 C-30,-23.2843 -23.2843,-30 -15,-30 C-6.71573,-30 0,-23.2843 0,-15 "/>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M-5,-15 C-5,-9.47715 -9.47715,-5 -15,-5 C-20.5228,-5 -25,-9.47715 -25,-15 C-25,-20.5228 -20.5228,-25 -15,-25 C-9.47715,-25 -5,-20.5228 -5,-15 "/>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M-10,-15 C-10,-12.2386 -12.2386,-10 -15,-10 C-17.7614,-10 -20,-12.2386 -20,-15 C-20,-17.7614 -17.7614,-20 -15,-20 C-12.2386,-20 -10,-17.7614 -10,-15 "/>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,319,236)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>

<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
</g>
</g>
</svg>
Сразу бросается в глаза отличие
<path vector-effect="non-scaling-stroke">
У вас там просто none
 
Не подскажите как пропарсить данный файл???
Заранее спасибо)).
 
 
 

Там в коде  у меня есть:

gNode.firstChildElement("rect"); 
Вам же стоит использовать просто path в данном случае.
gNode.firstChildElement("path"); 
Аттрибуты забирать аналогично, как они забираются из rect в моём коде. Делайте по аналогии, при возникновении некоторых проблем используйте qDebug() что понять, что идёт не так.
F

Для формирования задал объект QGraphiscPathItem

QGraphicsPathItem *rect = new QGraphicsPathItem();
rect->setFlag(QGraphicsRectItem::ItemIsMovable);
QDomElement gElement = gNode.toElement();
rect->setPath();
у тега path есть атрибут "d". Пытаюсь считать этот атрибут с помощью setPath, который требует параметры типа QPainterPath
Как передать методу данные параметры в требуемом типе и правильно ли я сделал воспользовавшись QGraphicsPathItem?
F

А кажется понял, я должен из атрибутов path сформировать заново элементы Ellipse, просто нужно правильно подобрать эти атрибуты.....


Ну да. Там должны быть координаты, их нужно пропарсить и по ним построить Path, либо преобразовать их в эллипс. Вообще, кое-что кривовато переносится в SVG местами.

c
  • #
  • 15 октября 2017 г. 10:27

How can I open another polygon type such as circle(ellipse) ?

The principle will be similar. You need to research content of svg file and make parsing of needed tag.

For Example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   viewBox="0 0 744.09448819 1052.3622047"
   id="svg2"
   version="1.1"
   inkscape:version="0.91 r13725"
   sodipodi:docname="circle.svg">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.49497475"
     inkscape:cx="405.75379"
     inkscape:cy="583.59967"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1366"
     inkscape:window-height="703"
     inkscape:window-x="0"
     inkscape:window-y="0"
     inkscape:window-maximized="1" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <rect
       style="fill:#0000ff;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       id="rect3336"
       width="222.23357"
       height="131.31982"
       x="125.25892"
       y="219.99651" />
    <ellipse
       style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
       id="path3338"
       cx="287.89346"
       cy="466.47372"
       rx="89.90358"
       ry="74.751289" />
  </g>
</svg>
In this code You can try to get ellipse.
Method for parsing will be same.
QList<QGraphicsEllipseItem*> SvgReader::getEllipses(const QString filename)
{
    QList<QGraphicsEllipseItem *> ellipsesList;

    QDomDocument doc;
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return ellipsesList;

    QDomNodeList gList = doc.elementsByTagName("g");
    for (int i = 0; i < gList.size(); i++) {
        QDomNode gNode = gList.item(i);
        QDomElement ellipseElement = gNode.firstChildElement("ellipse");

        if (ellipseElement.isNull()){
            continue;
        } else {
            QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem();
            ellipseItem->setFlag(QGraphicsItem::ItemIsMovable);

            QDomElement gElement = gNode.toElement();
            ellipseItem->setRect(ellipseElement.attribute("cx").toFloat() - ellipseElement.attribute("rx").toFloat(),
                                 ellipseElement.attribute("cy").toFloat() - ellipseElement.attribute("ry").toFloat(),
                                 ellipseElement.attribute("rx").toFloat() * 2,
                                 ellipseElement.attribute("ry").toFloat() * 2);

            QColor fillColor(ellipseElement.attribute("style").split(";").at(0).split(":").at(1));
            ellipseItem->setBrush(QBrush(fillColor));

            QColor strokeColor(gElement.attribute("stroke", "#000000"));
            strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());

            ellipseItem->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
            ellipsesList.append(ellipseItem);
        }
    }
    file.close();
    return ellipsesList;
}
c

Thank You sir, So how can I change this method


QRectF SvgReader::getSizes(const QString filename)
{
    QDomDocument doc;       // initialize the stack object QDomDocument
    QFile file(filename);   // Open your SVG-file
    // If it is not opened, or have failed to transmit the contents in QDocDocument
    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return QRectF(0,0,200,200); // the return values for the default scene
 
    /* Then pick up a list of items with the tag svg.
      * If a list of elements is not empty,
      * take the size of the graphic scenes.
     * */
    QDomNodeList list = doc.elementsByTagName("svg");
    if(list.length() > 0) {
        QDomElement svgElement = list.item(0).toElement();
        QStringList parameters = svgElement.attribute("viewBox").split(" ");
        return QRectF(parameters.at(0).toInt(),
                      parameters.at(1).toInt(),
                      parameters.at(2).toInt(),
                      parameters.at(3).toInt());
    }
    return QRectF(0,0,200,200);
}

which class I need to use instead of QRectF

For what You want to use another class instead of QRectF?

This static method return just size of QGraphicsScene from svg file. QRectF should be enough.
c
  • #
  • 16 октября 2017 г. 16:09

Sir,I tried your code for open ellipse item.but my program not open ellipse item.what should I need to do?


here is my code :

readsvg.cpp

QList<QGraphicsEllipseItem*> ReadSVG::getEllipses(const QString filename)
{
    QList<QGraphicsEllipseItem *> ellipsesList;

    QDomDocument doc;
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return ellipsesList;

    QDomNodeList gList = doc.elementsByTagName("g");
    for (int i = 0; i < gList.size(); i++) {
        QDomNode gNode = gList.item(i);
        QDomElement ellipseElement = gNode.firstChildElement("ellipse");

        if (ellipseElement.isNull()){
            continue;
        } else {
            QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem();
            ellipseItem->setFlag(QGraphicsItem::ItemIsMovable);

            QDomElement gElement = gNode.toElement();
            ellipseItem->setRect(ellipseElement.attribute("cx").toFloat() - ellipseElement.attribute("rx").toFloat(),
                                 ellipseElement.attribute("cy").toFloat() - ellipseElement.attribute("ry").toFloat(),
                                 ellipseElement.attribute("rx").toFloat() * 2,
                                 ellipseElement.attribute("ry").toFloat() * 2);

            QColor fillColor(ellipseElement.attribute("style").split(";").at(0).split(":").at(1));
            ellipseItem->setBrush(QBrush(fillColor));

            QColor strokeColor(gElement.attribute("stroke", "#000000"));
            strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());

            ellipseItem->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
            ellipsesList.append(ellipseItem);
        }
    }
    file.close();
    return ellipsesList;
}


QRectF ReadSVG::getSizes(const QString filename)
{
    QDomDocument doc;       // initialize the QDomDocument object on the stack
    QFile file(filename);   // Open our SVG file
    // If it did not open or could not transfer content to QDocDocument
    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return QRectF(0,0,200,200); // then return the values ​​for the default scene
    QDomNodeList list = doc.elementsByTagName("svg");
    if(list.length() > 0) {
        QDomElement svgElement = list.item(0).toElement();
        QStringList parameters = svgElement.attribute("viewBox").split(" ");
        return QRectF(parameters.at(0).toInt(),
                      parameters.at(1).toInt(),
                      parameters.at(2).toInt(),
                      parameters.at(3).toInt());
    }
    return QRectF(0,0,200,200);
}
widget.cpp

void Widget::on_btnOpen_clicked()
{
    QString newPath = QFileDialog::getOpenFileName(this, trUtf8("Open SVG"),
                                                   path, tr("SVG files (*.svg)"));
    if (newPath.isEmpty())
        return;

    path = newPath;
    scene->clear();

    scene->setSceneRect(ReadSVG::getSizes(path));
    foreach (QGraphicsEllipseItem *itemE, ReadSVG::getEllipses(path)) {
        QGraphicsEllipseItem *elips = itemE;
        scene->addItem(elips);
    }


}

I think You have another version of SVG file. First, need to see content of SVG file. It is simple XML-format, therefore just need to research content.

Do You want just open SVG file or make special graphics object (from QGraphicsItem etc.), which you will change it on QGraphicsScene?
If You want just open SVG file without changes, You can use QSvgWidget for it.
Otherwise, I suggest You create topic on forum of this site , where You can attach svg file, and we continue discuss about this issue.
c

Sir I post is as a topic,please help me to solve this problem

Скажите пожалуйста, как пользоваться QSvgRenderer и загружать целиком в QGraphicsScene ?
Если делаю так, то получаю белый экран:

    QString newPath = QFileDialog::getOpenFileName(this, trUtf8("Open SVG"),
                                                   path, tr("SVG files (*.svg)"));

    if (newPath.isEmpty())
            return;

        path = newPath;
        scene->clear();

        QSvgRenderer w;
        w.load(path);
        scene->setSceneRect(w.viewBoxF());

А если делаю с помощью вашего класса, то тоже получаю белый экрак.
Рисую на сцене так: Qt/C++ - Урок 021. Рисование мышью в Qt

Вот так целиком добавлять можно

    QString newPath = QFileDialog::getOpenFileName(this, trUtf8("Open SVG"),
                                                   path, tr("SVG files (*.svg)"));

    if (newPath.isEmpty())
            return;

        path = newPath;
        scene->clear();

        //QSvgRenderer myRenderer;
        QSvgRenderer* myRenderer = new QSvgRenderer();
        myRenderer->load(path);
        //scene->setSceneRect(myRenderer->viewBoxF());
        QGraphicsSvgItem *myItem = new QGraphicsSvgItem();
        myItem->setSharedRenderer(myRenderer);
        scene->addItem(myItem);

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
VD

C++ - Тест 001. Первая программа и типы данных

  • Результат:73баллов,
  • Очки рейтинга1
Ds

C++ - Тест 003. Условия и циклы

  • Результат:64баллов,
  • Очки рейтинга-1
o

C++ - Тест 001. Первая программа и типы данных

  • Результат:86баллов,
  • Очки рейтинга6
Последние комментарии
s

Django - Урок 023. Like Dislike система с помощью GenericForeignKey

все, я со всем разобрался!) Извините!)
s

Django - Урок 023. Like Dislike система с помощью GenericForeignKey

Доброго времени суток!) Я случайно набрел на вашу статью, и она помогла мне решить некоторые мои трудности, я прошел за вами по шагам, в попытках адаптировать это под себя, и возник вопрос. У ва…
R

Qt/C++ - Урок 026. Применение CallBack функции

Спасибо огромное!

Qt/C++ - Урок 026. Применение CallBack функции

Если не объявлять статической, то не соберётся. Не получится сделать привязку метода. Дело в том, что в процессе компиляции производится сборка с указанием конкретных участков кода в данном…
  • Anton
  • 4 августа 2020 г. 2:25

Django - Урок 039. Добавление личных сообщений и чатов на сайте - Часть 2 (Счётчик диалогов и чатов с непрочитанными сообщениями)

Может быть посоветуете как добавить необязательное поле + прокинуть его во вьюху что бы можно было отправлять небольшие документы.?
Сейчас обсуждают на форуме
s

Ключевое слово class

Если закоментить include , то ошибка будет такая : C2027(использование неопределённого типа "Autorization"). Если убрать ключевое слово class , то ошибки будет 3 : Ошибка C2143 син…

Как в Android открыть свернутое приложение?

Может быть поможет это

Динамическое изменение цветовой схемы material

как по мне, темы типа material хороши если вас полностью устраивает их стил, если пишете кастомный дизайн то имеет смысл отказаться

QT QGraphics преобразование координат

Добрый день. Да, можно перевести в координаты экрана. Используйте метод mapToGlobal() . В Qt документации на класс приводятся методы, которые внедрены в конкретном классе. В нач…
М

QML связь с моделью в C++

Спасибо.
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB