Документ интерфейса
- Все известные подинтерфейсы:
StyledDocument
- Все известные реализующие классы:
-
AbstractDocument,DefaultStyledDocument,HTMLDocument,PlainDocument
public interface Document
Интерфейс Document служит контейнером для текста, являющимся моделью для компонентов Swing, отображающих текст. Цель этого интерфейса — масштабирование от очень простых задач (простого текстового поля) до сложных (например, HTML или XML документа).
Содержимое
На самом простом уровне текст может быть представлен как линейная последовательность символов. Для поддержки локализации модель Swing для текста использует символы Юникода. Последовательность символов, отображаемых в текстовом компоненте, обычно называется содержимым компонента.
Для обозначения местоположений в последовательности используются координаты между двумя символами. Как показано на диаграмме ниже, местоположение в текстовом документе может обозначаться как позиция или смещение. Эта позиция нулевая.
В примере, если содержимое документа — последовательность "Быстрая коричневая лиса", как показано на предыдущей диаграмме, местоположение перед словом "Быстрая" равно 0, а местоположение после слова "Быстрая" и перед последующим пробелом равно 3. Вся последовательность символов в последовательности "Быстрая" называется диапазоном.
Следующие методы предоставляют доступ к данным символов, составляющих содержимое.
Структура
Текст редко представляется просто как бессвязное содержимое. Обычно текст имеет некоторую структуру. Точная модель структуры зависит от конкретной реализации документа. Она может быть простой (без структуры, т. е. простое текстовое поле) или же, как показано на диаграмме ниже.
Единица структуры (т. е. узел дерева) обозначается интерфейсом Element. Каждый элемент может быть помечен набором атрибутов. Эти атрибуты (парные имя/значение) определяются интерфейсом AttributeSet.
Следующие методы обеспечивают доступ к структуре документа.
Изменения
Все документы должны уметь добавлять и удалять простой текст. Обычно текст вставляется и удаляется через действия с клавиатуры или мыши. Какое влияние вставка или удаление окажут на структуру документа, целиком зависит от реализации документа.
Следующие методы связаны с изменениями содержимого документа:
-
insertString(int, java.lang.String, javax.swing.text.AttributeSet) -
remove(int, int) -
createPosition(int)
Уведомления
Изменения в Document должны быть сообщены заинтересованным наблюдателям. Уведомление об изменениях следует принципам модели событий, определённым для JavaBeans. В модели событий JavaBeans, после отправки уведомления об событии, все слушатели должны быть уведомлены до любых дальнейших изменений источника события. Порядок доставки не гарантируется.
Уведомление предоставляется в виде двух отдельных событий, DocumentEvent и UndoableEditEvent. Если изменение выполняется в Document через его API, то DocumentEvent будет отправлено всем зарегистрированным DocumentListeners. Если реализация Document поддерживает возможности отмены/повтор, UndoableEditEvent будет отправлено всем зарегистрированным UndoableEditListener. Если отменяется выполнение редактирования, то DocumentEvent должно быть сгенерировано документом, чтобы указать, что он снова изменился. В этом случае не должно генерироваться UndoableEditEvent, так как это редактирование является источником изменения, а не изменением Document через его API.
Ссылаясь на диаграмму выше, предположим, что компонент слева изменяет объект документа, представленный синим прямоугольником. Документ отвечает, отправляя событие DocumentEvent в оба визуальных компонента и отправляет событие UndoableEditEvent в слушающую логику, которая поддерживает буфер истории.
Теперь предположим, что компонент справа изменяет тот же документ. Опять же, документ отправляет событие DocumentEvent в оба визуальных компонента и отправляет событие UndoableEditEvent в слушающую логику, поддерживающую буфер истории.
Если затем буфер истории откатывается (т. е. последнее UndoableEdit отменено), в оба представления отправляется DocumentEvent, заставляя их отражать отменённое изменение в документе (то есть удаление изменения компонента справа). Если буфер истории ещё раз откатывается назад, то в оба представления отправляется ещё один DocumentEvent, заставляя их отразить отменённое изменение в документе — то есть удаление изменения компонента слева.
Методы, связанные с наблюдением за изменениями в документе:
-
addDocumentListener(DocumentListener) -
removeDocumentListener(DocumentListener) -
addUndoableEditListener(UndoableEditListener) -
removeUndoableEditListener(UndoableEditListener)
Свойства
Реализации документов обычно имеют набор свойств, связанных с ними во время выполнения. Два хорошо известных свойства — StreamDescriptionProperty, которое можно использовать для описания источника Document, и TitleProperty, которое можно использовать для именования Document. Методы, связанные со свойствами:
Обзор и советы по программированию
Element — важный интерфейс, используемый при создании документа. Он может описывать различные структурные части документа, такие как абзацы, строки текста или даже (в HTML-документах) элементы списков. По сути, интерфейс Element воплощает некоторые аспекты SGML-документа. Поэтому, если вы знакомы с SGML, вы, возможно, уже понимаете интерфейс Element Swing.
В модели документа Swing API интерфейс Element определяет структурный фрагмент документа, например, абзац, строку текста или элемент списка в HTML-документе.
Каждый элемент является либо ветвью, либо листом. Если элемент является ветвью, то метод isLeaf() возвращает false. Если элемент является листом, то isLeaf() возвращает true.
Ветви могут иметь любое количество дочерних элементов. У листов нет дочерних элементов. Чтобы определить, сколько дочерних элементов у ветви, можно вызвать getElementCount(). Чтобы определить родителя элемента, можно вызвать getParentElement(). У корневых элементов нет родителей, поэтому вызов getParentElement() для корня возвращает null.
Элемент представляет собой определённый фрагмент документа, начинающийся с startOffset и заканчивающийся перед endOffset. Начальное смещение элемента-ветви обычно совпадает с начальным смещением первого дочернего элемента. Аналогично, конечное смещение элемента-ветви обычно совпадает с конечным смещением последнего дочернего элемента.
Каждый элемент связан с набором атрибутов, к которому можно получить доступ, вызвав getAttributes(). В элементе набор атрибутов — это набор пар ключ/значение. Эти пары обычно используются для разметки — например, для определения цвета фона элемента, размера шрифта и т. д. Но именно модель и разработчик определяют, что хранится в наборе атрибутов.
Корневой (или корневые) элемент документа можно получить, вызвав методы getDefaultRootElement() и getRootElements(), которые определены в интерфейсе Document.
Интерфейс Document отвечает за перевод линейного представления символов в операции с элементами. Каждая реализация документа определяет структуру элементов.
Класс PlainDocument
Класс PlainDocument определяет структуру элементов, в которой корневой узел содержит дочерний узел для каждой строки текста в модели. Рисунок 1 показывает, как две строки текста моделируются с помощью PlainDocument
Рисунок 2 показывает, как те же две строки текста могут отображаться в фактическом содержимом:
Вставка текста в PlainDocument
Как уже упоминалось, PlainDocument содержит корневой элемент, который, в свою очередь, содержит элемент для каждой строки текста. Когда текст вставляется в PlainDocument, он создаёт элементы, необходимые для существования элемента для каждой новой строки. Например, предположим, что вы хотите вставить новую строку в позиции 2 на рисунке 2. Для этого можно использовать метод Document insertString(), используя такой синтаксис:
document.insertString(2, "\n", null); После вызова метода insertString() структура элементов будет выглядеть как на рисунке 3.
В качестве другого примера, предположим, что вы хотите вставить шаблон "new\ntext\n" в позицию 2, как показано ранее на рисунке 2. Эта операция приведет к результату, показанному на рисунке 4.
На предыдущих иллюстрациях имя элементов строки изменяется после вставки для соответствия номерам строк. Но обратите внимание, что при этом наборы атрибутов остаются неизменными. Например, на рисунке 2 набор атрибутов строки 2 соответствует набору атрибутов строки 4 на рисунке 4.
Удаление текста из PlainDocument
Удаление текста приводит к изменению структуры, если удаление охватывает более одной строки. Рассмотрим удаление семи символов, начиная с смещения 1 на рисунке 3. В этом случае элемент, представляющий строку 2, полностью удаляется, так как область, которую он представляет, находится в области удаления. Элементы, представляющие строки 1 и 3, объединяются, так как они частично находятся в области удаления. Таким образом, мы получаем результат:
Класс DefaultStyledDocument
Класс DefaultStyledDocument, используемый для форматированного текста, содержит ещё один уровень элементов. Этот дополнительный уровень необходим для того, чтобы каждый абзац мог содержать различные стили текста. В двух абзацах, показанных на рисунке 6, первый абзац содержит два стиля, а второй — три стиля.
Рисунок 7 показывает, как эти же элементы могут быть отображены в содержании.
Вставка текста в DefaultStyledDocument
Как уже упоминалось, DefaultStyledDocument поддерживает структуру элементов таким образом, что корневой элемент содержит дочерний элемент для каждого абзаца. В свою очередь, каждый из этих элементов абзаца содержит элемент для каждого стиля текста в абзаце. Например, предположим, что у вас есть документ, содержащий один абзац, и этот абзац содержит два стиля, как показано на рисунке 8.
Если затем вы захотите вставить перевод строки в позиции 2, вы снова используете метод insertString(), как показано ниже:
styledDocument.insertString(2, "\n",
styledDocument.getCharacterElement(0).getAttributes()); Этот операция приведет к результату, показанному на рисунке 9.
Важно отметить, что AttributeSet, переданный в insertString(), соответствует атрибутам стиля 1. Если AttributeSet, переданный в insertString(), не соответствует, результат будет таким, как показано на рисунке 10.
Удаление текста из DefaultStyledDocument
Удаление текста из DefaultStyledDocument аналогично удалению текста из PlainDocument. Единственное различие заключается в дополнительном уровне элементов. Представьте, что произойдет, если вы удалите два символа в позиции 1 на рисунке 10 выше. Поскольку второй элемент абзаца 1 полностью находится в области удаления, он будет удален. Предполагая, что атрибуты первого дочернего элемента абзаца 1 соответствуют атрибутам первого дочернего элемента абзаца 2, результатом будет то, что показано на рисунке 11.
Если атрибуты не совпадают, мы получим результаты, показанные на рисунке 12.
Класс StyledDocument
Класс StyledDocument предоставляет метод setCharacterAttributes(), который позволяет установить атрибуты для элементов символов в заданном диапазоне:
public void setCharacterAttributes
(int offset, int length, AttributeSet s, boolean replace); Обратите внимание, что на диаграммах, показанных в предыдущем разделе, все листовые элементы, показанные на рисунках, также являются элементами символов. Это означает, что метод setCharacterAttributes() может использоваться для установки их атрибутов.
Метод setCharacterAttributes() принимает четыре аргумента. Первые два аргумента идентифицируют область в документе, которая должна быть изменена. Третий аргумент указывает новые атрибуты (в виде AttributeSet), а четвёртый аргумент определяет, следует ли добавлять новые атрибуты к существующим атрибутам (значение false) или следует ли заменить существующие атрибуты элемента символа новыми атрибутами (значение true).
Например, предположим, что вы хотите изменить атрибуты первых трех символов на рисунке 9, показанном ранее. Первые два аргумента, передаваемые методу setCharacterAttributes(), будут 0 и 3. Третий аргумент будет AttributeSet, содержащий новые атрибуты. В рассматриваемом примере значение четвертого аргумента не имеет значения.
Поскольку начальная и конечная позиции изменённой области (0 и 3) попадают на границы элементов символов, изменения структуры не требуются. То есть изменятся только атрибуты стиля элемента символа 1.
Теперь давайте рассмотрим пример, который требует изменения структуры. Вместо изменения первых трех символов на рисунке 9, давайте изменим первые два символа. Поскольку конечная позиция изменения (2) не попадает на границу элемента символа, элемент в позиции 2 должен быть разделен таким образом, чтобы позиция 2 была границей двух элементов. Вызов setCharacterAttributes() с начальной позицией 0 и длиной 2 приводит к результату, показанному ранее на рисунке 10.
Изменение атрибутов абзацев в StyledDocument
Класс StyledDocument предоставляет метод setParagraphAttributes(), который можно использовать для изменения атрибутов элемента абзаца:
public void setParagraphAttributes
(int offset, int length, AttributeSet s, boolean replace); Этот метод аналогичен методу setCharacterAttributes(), но он позволяет изменять атрибуты элементов абзаца. Реализация StyledDocument определяет, какие элементы являются абзацами. DefaultStyledDocument интерпретирует элементы абзацев как родительские элементы элементов символов. Вызов этого метода не приводит к изменению структуры; изменяются только атрибуты элемента абзаца.
Рекомендуется изучить EditorKit и View. View отвечает за отображение конкретного элемента, а EditorKit отвечает за ViewFactory, который может определить, какой View должен быть создан на основе элемента.
- См. также:
Краткое описание полей
| Модификатор и тип | Поле | Описание |
|---|---|---|
static final String |
StreamDescriptionProperty |
Имя свойства для описания потока, используемого для инициализации документа. |
static final String |
TitleProperty |
Имя свойства для заголовка документа, если он есть. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
void |
addDocumentListener |
Регистрирует данного наблюдателя для получения уведомлений об изменениях в документе. |
void |
addUndoableEditListener |
Регистрирует данного наблюдателя для получения уведомлений об обратимых изменениях в документе. |
Position |
createPosition |
Этот метод позволяет приложению отмечать место в последовательности текстового контента. |
Element |
getDefaultRootElement() |
Возвращает корневой элемент, на основе которого должны быть созданы представления, если не указан другой механизм для назначения представлений элементам. |
Position |
getEndPosition() |
Возвращает позицию, представляющую конец документа. |
int |
getLength() |
Возвращает количество символов в документе. |
Object |
getProperty |
Получает свойства, связанные с документом. |
Element[] |
getRootElements() |
Возвращает все определённые корневые элементы. |
Position |
getStartPosition() |
Возвращает позицию, представляющую начало документа. |
String |
getText |
Получает текст, содержащийся в заданной части документа. |
void |
getText |
Получает текст, содержащийся в заданной части документа. |
void |
insertString |
Вставляет строку контента. |
void |
putProperty |
Связывает свойство с документом. |
void |
remove |
Удаляет часть контента документа. |
void |
removeDocumentListener |
Отписывает данного наблюдателя от списка уведомлений, чтобы он больше не получал обновлений об изменениях. |
void |
removeUndoableEditListener |
Отписывает данного наблюдателя от списка уведомлений, чтобы он больше не получал обновлений. |
void |
render |
Позволяет безопасно отображать модель в условиях конкурентного доступа, если модель поддерживает асинхронное обновление. |
Подробное описание полей
StreamDescriptionProperty
static final String StreamDescriptionProperty
- См. также:
TitleProperty
static final String TitleProperty
- См. также:
Подробное описание методов
getLength
int getLength()
- Возвращает:
- количество символов >= 0
addDocumentListener
void addDocumentListener(DocumentListener listener)
- Параметры:
-
listener- наблюдатель для регистрации - См. также:
removeDocumentListener
void removeDocumentListener(DocumentListener listener)
- Параметры:
-
listener- наблюдатель для регистрации - См. также:
addUndoableEditListener
void addUndoableEditListener(UndoableEditListener listener)
- Параметры:
-
listener- наблюдатель для регистрации - См. также:
removeUndoableEditListener
void removeUndoableEditListener(UndoableEditListener listener)
- Параметры:
-
listener- наблюдатель для регистрации - См. также:
getProperty
Object getProperty(Object key)
- Параметры:
-
key- ключ свойства, не являющегосяnull - Возвращает:
- свойства
- См. также:
putProperty
void putProperty(Object key, Object value)
StreamDescriptionProperty и TitleProperty. Также могут быть определены другие свойства, например, автор.- Параметры:
-
key- ключ свойства, не являющегосяnull -
value- значение свойства - См. также:
remove
void remove(int offs, int len) throws BadLocationException
Для обеспечения приемлемого поведения в условиях конкурентного доступа, событие рассылается после того, как произошла мутация. Это означает, что к моменту отправки уведомления об удалении документ уже обновлен, а любые метки, созданные createPosition, уже изменены. При удалении конец диапазона удаления сворачивается до начала диапазона, а все метки в диапазоне удаления сворачиваются до начала диапазона.
Если структура документа изменилась в результате удаления, подробности о том, какие элементы были вставлены и удалены в ответ на изменение, также будут содержаться в сгенерированном DocumentEvent. Реализация документа сама решает, как должна измениться структура в ответ на удаление.
Если документ поддерживает отмену/повтор, также будет сгенерировано UndoableEditEvent.
- Параметры:
-
offs- смещение от начала >= 0 -
len- количество символов для удаления >= 0 - Исключения:
-
BadLocationException- какая-то часть диапазона удаления не являлась действительной частью документа. Положение в исключении - первая встреченная неверная позиция. - См. также:
insertString
void insertString(int offset, String str, AttributeSet a) throws BadLocationException
Если структура документа изменилась в результате вставки, подробности о том, какие элементы были вставлены и удалены в ответ на изменение, также будут содержаться в сгенерированном DocumentEvent. Реализация документа сама решает, как должна измениться структура в ответ на вставку.
Если документ поддерживает отмену/повтор, также будет сгенерировано UndoableEditEvent.
- Параметры:
-
offset- смещение в документе для вставки содержимого >= 0. Все позиции, отслеживающие изменения в или после заданной позиции, будут перемещены. -
str- строка для вставки -
a- атрибуты, связанные с вставляемым содержимым. Может быть null, если атрибутов нет. - Исключения:
-
BadLocationException- заданная позиция вставки не является допустимой позицией в документе - См. также:
getText
String getText(int offset, int length) throws BadLocationException
- Параметры:
-
offset- смещение в документе, представляющее желаемый старт текста >= 0 -
length- длина желаемой строки >= 0 - Возвращает:
- текст, в строке длины >= 0
- Исключения:
-
BadLocationException- какая-то часть заданного диапазона не являлась действительной частью документа. Положение в исключении - первая встреченная неверная позиция.
getText
void getText(int offset, int length, Segment txt) throws BadLocationException
Если свойство partialReturn объекта txt равно false, возвращаемые данные в Segment будут иметь полную запрошенную длину и могут или не могут быть копией, в зависимости от того, как данные хранятся. Если свойство partialReturn равно true, возвращается только количество текста, которое можно вернуть без создания копии. Использование частичных возвратов обеспечит лучшую производительность в ситуациях, когда сканируются большие части документа. Следующий пример демонстрирует использование частичного возврата для доступа ко всему документу:
int nleft = doc.getDocumentLength();
Segment text = new Segment();
int offs = 0;
text.setPartialReturn(true);
while (nleft > 0) {
doc.getText(offs, nleft, text);
// do something with text
nleft -= text.count;
offs += text.count;
}
- Параметры:
-
offset- смещение в документе, представляющее желаемый старт текста >= 0 -
length- длина желаемой строки >= 0 -
txt- объект Segment для возврата текста в - Исключения:
-
BadLocationException- какая-то часть заданного диапазона не являлась действительной частью документа. Положение в исключении - первая встреченная неверная позиция.
getStartPosition
Position getStartPosition()
- Возвращает:
- позицию
getEndPosition
Position getEndPosition()
- Возвращает:
- позицию
createPosition
Position createPosition(int offs) throws BadLocationException
- Параметры:
-
offs- смещение от начала документа >= 0 - Возвращает:
- позицию
- Исключения:
-
BadLocationException- если заданная позиция не представляет действительное местоположение в связанном документе
getRootElements
Element[] getRootElements()
Как правило, существует только одна структура документа, но интерфейс поддерживает создание произвольного числа структурных проекций над текстовыми данными. Документ может иметь несколько корневых элементов для поддержки нескольких структур документа. Примерами могут служить:
- Направление текста.
- Потоки лексем.
- Деревья разбора.
- Преобразования в форматы, отличные от родного.
- Спецификации изменений.
- Аннотации.
- Возвращает:
- корневой элемент
getDefaultRootElement
Element getDefaultRootElement()
- Возвращает:
- корневой элемент
render
void render(Runnable r)
- Параметры:
-
r- объектRunnableдля отрисовки модели
© 1993, 2023, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/21/docs/api/java.desktop/javax/swing/text/Document.html