Соңғы мақалада графикалық көрініс нысандарын 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* тегі тік** тегін орап алатын * тіктөртбұрыштың толтыру және контур түстерін, сонымен қатар контурдың қалыңдығын қамтиды. Оларды жою қажет болады.
mainwindow.ui
Бұл файлға тек жүктеу түймесі қосылады, сигнал бойынша біз файлды таңдау диалогын ашамыз және 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
Здравствуйте!
Там в коде у меня есть:
Для формирования задал объект QGraphiscPathItem
А кажется понял, я должен из атрибутов path сформировать заново элементы Ellipse, просто нужно правильно подобрать эти атрибуты.....
Ну да. Там должны быть координаты, их нужно пропарсить и по ним построить Path, либо преобразовать их в эллипс. Вообще, кое-что кривовато переносится в SVG местами.
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.
Thank You sir, So how can I change this method
For what You want to use another class instead of QRectF?
Sir,I tried your code for open ellipse item.but my program not open ellipse item.what should I need to do?
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.
Sir I post is as a topic,please help me to solve this problem
Скажите пожалуйста, как пользоваться QSvgRenderer и загружать целиком в QGraphicsScene ?
Если делаю так, то получаю белый экран:
А если делаю с помощью вашего класса, то тоже получаю белый экрак.
Рисую на сцене так: Qt/C++ - Урок 021. Рисование мышью в Qt
Вот так целиком добавлять можно