Пример "Text Object"
Файлы:
Пример "Text Object" показывает, как вставить файл SVG в QTextDocument.
QTextDocument состоит из иерархии элементов, таких как текстовые блоки и рамки. Текстовый объект описывает структуру или формат одного или более этих элементов. Например, импортированные из HTML изображения реализуются с использованием текстовых объектов. Текстовые объекты используются компоновщиком документа для размещения и визуализации (отрисовки) документа. Каждый объект знает как отрисовывать элементы, которыми они управляют, и как вычислять их размеры.
Чтобы получить возможность вставить изображение SVG в текстовый документ, мы создаём текстовый объект и реализуем отрисовку для этого объекта. Этот объект можно затем установить на QTextCharFormat. Также зарегистрируем текстовый объект с помощью компоновщика документа, разрешая отрисовывать объекты QTextCharFormat, управляемые нашим текстовым объектом. Резюмируем порядок действий с помощью следующих шагов:
Пример состоит из следующих классов:
- SvgTextObject реализует текстовый объект.
- Window показывает QTextEdit, в который можно вставлять изображения SVG.
Определение класса 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.
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) |
Торговые марки |
Qt 4.5.3 |
|