Реклама

Qt/C++ - Урок 044. Сохранение объектов QGraphicsScene в файл векторной графики SVG

CorelDraw, QGraphicsScene, Qt, SVG

С помощью библиотеки Qt можно сохранять содержимое графической сцены QGraphicsScene в файлы векторной графики формата SVG, которые после без проблем открываются в таких редакторах, как CorelDraw. Предлагаю написать небольшое приложение, которое позволит сохранить содержимое графической сцены в файл формата SVG, а потом откроем его с помощью CorelDraw .

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

  • SvgExample.pro - профайла проекта;
  • mainwindow.h - заголовочного файла главного окна приложения;
  • mainwindow.cpp - файла исходных кодов главного окна приложения, в котором и будет происходить всё действо;
  • mainwindow.ui - файл формы главного окна приложения;
  • main.cpp - основного стартового файла исходных кодов.

mainwindow.ui

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

SvgExample.pro

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

#-------------------------------------------------
#
# Project created by QtCreator 2016-03-09T23:52:59
#
#-------------------------------------------------

QT       += core gui svg

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = SvgExample
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

main.cpp

Файл остается без изменений.

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h

Итак, в заголовочном файле главного окна приложения подключим библиотеки QGraphicsScene , QGraphicsRectItem, QSvgGenerator, QFileDialog и QPainter.

На графической будет создано два прямоугольника, которые необходимо будет сохранить в файл SVG. Сохранение будет производиться в слоте обработки нажатия кнопки, которая будет вызывать диалоговое окно для выбора пути сохранения SVG файла.

#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();

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

#endif // MAINWINDOW_H

mainwindow.cpp

Для задания служебных параметров и отрисовки графических объектов с графической сцены используется объекта класса QSvgGenerator , но для передачи данных и непосредственной отрисовки в данный объект будет использоваться объекта класса QPainter , в который устанавливается целевой объект, в который будет производиться отрисовка с помощью метода begin(), а целью отрисовки будет непосредственно сам объект класса QSvgGenerator. Отрисовка будет произодиться с помощью метода графической сцены render(), через QPainter.

#include "mainwindow.h"
#include "ui_mainwindow.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);

    // Создаём первый красный прямоугольник на графической сцене
    QGraphicsRectItem *rect1 = new QGraphicsRectItem();
    rect1->setRect(10,50,100,50);
    rect1->setBrush(QBrush(Qt::red));
    rect1->setPen(QPen(QBrush(Qt::black),2));
    scene->addItem(rect1);

    // И создаём второй синий прямоугольник на графической сцене
    QGraphicsRectItem *rect2 = new QGraphicsRectItem();
    rect2->setRect(150,100,115,75);
    rect2->setBrush(QBrush(Qt::blue));
    rect2->setPen(QPen(QBrush(Qt::black),2));
    scene->addItem(rect2);
}

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

void MainWindow::on_saveButton_clicked()
{
    // Заберём путь к файлу и его имененем, который будем создавать
    QString newPath = QFileDialog::getSaveFileName(this, trUtf8("Save SVG"),
        path, tr("SVG files (*.svg)"));

    if (newPath.isEmpty())
        return;

    path = newPath;

    QSvgGenerator generator;        // Создаём объект генератора файла
    generator.setFileName(path);    // Устанавливаем путь к файлу, куда будет сохраняться векторная графика
    generator.setSize(QSize(scene->width(), scene->height()));  // Устанавливаем размеры рабочей области документа в миллиметрах
    generator.setViewBox(QRect(0, 0, scene->width(), scene->height())); // Устанавливаем рабочую область в координатах
    generator.setTitle(trUtf8("SVG Example"));                          // Титульное название документа
    generator.setDescription(trUtf8("File created by SVG Example"));    // Описание документа

    // С помощью класса QPainter
    QPainter painter;
    painter.begin(&generator);  // Устанавливаем устройство/объект в котором будем производить отрисовку
    scene->render(&painter);    // Отрисовываем содержимое сцены с помощью painter в целевое устройство/объект
    painter.end();              // Заканчиваем отрисовку

    // По окончанию отрисовки получим векторный файл с содержимым графической сцены
}

Итог

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

  1. SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene

Видеоурок

Реклама

Комментарии

Добрый вечер. Встал вопрос. Каким образом сохранить координаты объектов, потому что в следующем уроке объекты на сцене будут находиться все в одном месте из которого их еще придется перетаскивать

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

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
  • falcon
  • 16 января 2018 г. 17:25

Qt - Тест 001. Сигналы и слоты

  • Результат 100 баллов
  • Очки рейтинга 10
  • falcon
  • 16 января 2018 г. 17:22

Qt - Тест 001. Сигналы и слоты

  • Результат 68 баллов
  • Очки рейтинга -1
  • falcon
  • 16 января 2018 г. 17:18

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

  • Результат 73 баллов
  • Очки рейтинга 1
Последние комментарии

QML - Урок 021. Переключение между окнами в QML

Спасибо всем. Все получилось. Прикручиваю логику.

  • BlinCT
  • 14 января 2018 г. 19:28

Разработка на Qt под iOS

Вот честно, на сколько же муторно под огрызок что то делать. Куча проблем) А вод линь или под Андроид все просто и тривиально))

  • folax
  • 12 января 2018 г. 9:16

QML - Урок 021. Переключение между окнами в QML

Ничего сложного, делаете по тех заданию 3 файла qml, называете их как указанно в тех задании, потом из первого окна через Loader их переключаете, в окне 2 и 3 делаете сигналы которые при закры...

QML - Урок 021. Переключение между окнами в QML

Все верно, я и не говорил что этот кусок кода лично мое произведение. Это тоже верно: Это задание для прохождения на собеседование в одну из крупных украинских IT компаний. Логику ...

  • folax
  • 12 января 2018 г. 8:13

QML - Урок 021. Переключение между окнами в QML

int main(int argc, char *argv[]){ QApplication app(argc, argv); Logic logic; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("logic", &logic)...

Сейчас обсуждают на форуме

ChartView. Отображение метки данных точки серии при наведении курсора

Спасибо большущее за советы! Все получилось через ScatterSeries. Методы remove() как-то сходу не дались, удаляет в первый раз, а потом программа падает... Не стал тратить время и воспользовалс...

  • EVILEG
  • 16 января 2018 г. 14:23

Как проверить доступность сервера

Добрый день! Теоретически можно использовать QTcpSocket, у него есть метод connectToHost. Возможно, что проверка доступности через этот класс будет осуществляться несколько быстрее,...

QGraphicsScene

спасибо, за подробное объяснение строчки, а с зумом я разобрался, все работает

  • EVILEG
  • 15 января 2018 г. 17:21

Qt webgl

Насчёт проверки подключения клиента я не в курсе. Что касается экземпляров приложения, то из того, что я читал получается, что нет необходимости в нескольких экземплярах для нескольких кл...

  • EVILEG
  • 15 января 2018 г. 11:39

Проблема добавления #DEFINE при сборке CMak'ом

А Вы не пробовали сделать предкомпилированные библиотеки boost под свою систему, а потом уже подключать собранные библиотеки Boost`а? Просто один только boost может собираться на пару гиг...