Пример "Text Object"Файлы:
Пример "Text Object" показывает, как вставить файл SVG в QTextDocument. QTextDocument состоит из иерархии элементов, таких как текстовые блоки и рамки. Текстовый объект описывает структуру или формат одного или более этих элементов. Например, импортированные из HTML изображения реализуются с использованием текстовых объектов. Текстовые объекты используются компоновщиком документа для размещения и визуализации (отрисовки) документа. Каждый объект знает как отрисовывать элементы, которыми они управляют, и как вычислять их размеры. Чтобы получить возможность вставить изображение SVG в текстовый документ, мы создаём текстовый объект и реализуем отрисовку для этого объекта. Этот объект можно затем установить на QTextCharFormat. Также зарегистрируем текстовый объект с помощью компоновщика документа, разрешая отрисовывать объекты QTextCharFormat, управляемые нашим текстовым объектом. Резюмируем порядок действий с помощью следующих шагов:
Пример состоит из следующих классов:
Определение класса SvgTextObjectДавайте взглянем на заголовочный файл SvgTextObject: class SvgTextObject : public QObject, public QTextObjectInterface { Q_OBJECT Q_INTERFACES(QTextObjectInterface) public: QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format); void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format); }; Текстовый объект - это QObject, который реализует QTextObjectInterface. Обратите внимание на то, что первый класс, от которого наследуется, должен быть QObject, а также что вы должны использовать Q_INTERFACES, чтобы позволить Qt узнать о том, что ваш класс реализует QTextObjectInterface. Компоновшик документа хранит коллекцию текстовых объектов, сохранённых как объекты QObject, каждый из которых имеет ассоциированный тип объекта. Компоновщик приводит QObject к ассоциированному типу объекта в QTextObjectInterface. Функции intrinsicSize() и drawObject() затем используются для вычисления размера текстового объекта и его отрисовки. Реализация класса SvgTextObjectДля начала взглянем на функцию intrinsicSize(): QSizeF SvgTextObject::intrinsicSize(QTextDocument * /*doc*/, int /*posInDocument*/, const QTextFormat &format) { QImage bufferedImage = qVariantValue<QImage>(format.property(Window::SvgData)); QSize size = bufferedImage.size(); if (size.height() > 25) size *= 25.0 / (double) size.height(); return QSizeF(size); } intrinsicSize() вызывается компоновщиком для вычисления размера текстового объекта. Заметьте, что мы отрисовываем изображение SVG на QImage. Это из-за того, что визуализация SVG является достаточно дорогостоящей. Пример будет реагировать со слишком большой задержкой в случае больших изображений, если мы каждый раз отрисовываем их с помощью QSvgRenderer. void SvgTextObject::drawObject(QPainter *painter, const QRectF &rect, QTextDocument * /*doc*/, int /*posInDocument*/, const QTextFormat &format) { QImage bufferedImage = qVariantValue<QImage>(format.property(Window::SvgData)); painter->drawImage(rect, bufferedImage); } В drawObject() мы отрисовываем изображение SVG используя QPainter, предоставленный компоновщиком. Определение класса WindowКласс Window является автономным окном, которое имеет QTextEdit в которое могут быть вставлены изображения SVG. class Window : public QWidget { Q_OBJECT public: enum { SvgTextFormat = QTextFormat::UserObject + 1 }; enum SvgProperties { SvgData = 1 }; Window(); private slots: void insertTextObject(); private: void setupTextObject(); void setupGui(); private: QTextEdit *textEdit; QLabel *fileNameLabel; QLineEdit *fileNameLineEdit; QPushButton *insertTextObjectButton; }; Слот insertTextObject() вставляет изображение SVG в текущую позицию курсора, в то время как setupTextObject() создаёт и регистрирует SvgTextObject с помощью компоновщика документа текстового редактора. Конструктор просто вызывает setupTextObject() и setupGui(), которые создают и размещают виджеты в Window. Реализация класса WindowВзглянем поближе на то, как функции, относящиеся к текстовому объекту, начиная с функции setupTextObject(). void Window::setupTextObject() { QObject *svgInterface = new SvgTextObject; textEdit->document()->documentLayout()->registerHandler(SvgTextFormat, svgInterface); } Значением SvgTextFormat'а является количество наших типов объектов. Оно используется для идентификации типов объектов компоновщиком документа. Обратите внимание на то, что создаём только один экземпляр; он будет использоваться всеми QTextCharFormat'ми с помощью типа объекта SvgTextFormat. Перейдём к функции insertTextObject(): void Window::insertTextObject() { QString fileName = fileNameLineEdit->text(); QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::warning(this, tr("Error Opening File"), tr("Could not open '%1'").arg(fileName)); } QByteArray svgData = file.readAll(); Во-первых, файл .svg открыт и его содержимое прочитано в массив svgData. QTextCharFormat svgCharFormat; svgCharFormat.setObjectType(SvgTextFormat); QSvgRenderer renderer(svgData); QImage svgBufferImage(renderer.defaultSize(), QImage::Format_ARGB32); QPainter painter(&svgBufferImage); renderer.render(&painter, svgBufferImage.rect()); svgCharFormat.setProperty(SvgData, svgBufferImage); QTextCursor cursor = textEdit->textCursor(); cursor.insertText(QString(QChar::ObjectReplacementCharacter), svgCharFormat); textEdit->setTextCursor(cursor); } Чтобы увеличить скорость работы, мы помещаем изображение SVG в буфер QImage. Используем setProperty() для хранения QImage в QTextCharFormat. Мы можем его позднее с помощью property(). Формат символов вставляем обычным способом - используем QTextCursor. Заметьте, что мы использовали специальный QChar - ObjectReplacementCharacter. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |