© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

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

QGraphicsScene, Qt, SVG, Svg Reader

В прошлой статье был рассмотрен пример того, как сохранить объекты графической сцены в файл 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

Видеоурок

Комментарии

12 августа 2017 г. 12: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
 
Не подскажите как пропарсить данный файл???
Заранее спасибо)).
 
 
 
13 августа 2017 г. 7:56

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

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

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

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

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


15 августа 2017 г. 9:04

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

15 октября 2017 г. 14:27

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

15 октября 2017 г. 18:52

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;
}
16 октября 2017 г. 13:53

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
16 октября 2017 г. 15:25

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.
16 октября 2017 г. 20: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);
    }


}
17 октября 2017 г. 5:44

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.
17 октября 2017 г. 9:29

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

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
15 июня 2018 г. 12:42
Nicky

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат 100 баллов
  • Очки рейтинга 10
15 июня 2018 г. 12:36
Nicky

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

  • Результат 57 баллов
  • Очки рейтинга -2
15 июня 2018 г. 12:29
Nicky

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

  • Результат 46 баллов
  • Очки рейтинга -6
Последние комментарии
18 июня 2018 г. 7:12
EVILEG

PyQt5 - Урок 007. Работаем с QML QtQuick (Сигналы и слоты)

Я вот сейчас банальность скажу, но у меня всё работало. Так что даже и не знаю, надо на код смотреть, что ещё у вас добавлено или отсутствует из библиотек. P/S/ Извините, вы сейчас вс...
18 июня 2018 г. 7:10
EVILEG

Qt/C++ - Урок 042. PopUp уведомление в стиле Gnome с помощью Qt

Недоработки, вряд ли этот зверь вообще является официально поддерживаемым
18 июня 2018 г. 7:01
EVILEG

QML - Урок 016. База данных SQLite и работа с ней в QML Qt

что-то мне сдаётся, что здесь просто пересобрать проект нужно с удалением build каталога
18 июня 2018 г. 7:00
EVILEG

Qt - WinAPI. Как показать запущенное приложение поверх своего приложения

Если зарыться в API системы, то, думаю, что можно, тут тоже использовался WinAPI.
16 июня 2018 г. 15:19
pro100belik

Qt - WinAPI. Как показать запущенное приложение поверх своего приложения

А можно по ID процесса  выводить на передний план окно? myProcess->processId();
Сейчас обсуждают на форуме
19 июня 2018 г. 7:56
EVILEG

как редактировать порядок обхода этементов по нажатию TAB в Qt5 qml

Что-то наподобие такого TextField { Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()}
19 июня 2018 г. 6:31
kabanov

Как сохранить фокус в TextField после перезагрузки модели

Rectangle { ListView { id: listView delegate: Item { id: cDelegate Item { Row { ComboBox { ...
18 июня 2018 г. 10:51
alex_lip

Qml and JavaScript

В том то и дело что просто в JS так нельзя Если использовать state - onReleased - не нужен вот так все работает Text { ...
18 июня 2018 г. 7:16
EVILEG

почему не выполняется код после вызова слота?

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

Рекомендуемые страницы