Документ интерфейса
- Все известные подинтерфейсы:
StyledDocument
- Все известные реализующие классы:
-
AbstractDocument,DefaultStyledDocument,HTMLDocument,PlainDocument
public interface Document
Интерфейс Document — это контейнер для текста, который служит моделью для текстовых компонентов Swing. Цель этого интерфейса — масштабироваться от очень простых потребностей (простого текстового поля) до сложных (например, HTML- или XML-документа).
Содержимое
На самом простом уровне текст может быть смоделирован как линейная последовательность символов. Для поддержки интернационализации модель текста Swing использует символы Unicode. Последовательность символов, отображаемых в текстовом компоненте, обычно называется содержимым компонента.
Для ссылки на расположения в последовательности используются координаты, расположенные между двумя символами. Как показано на диаграмме ниже, расположение в текстовом документе можно обозначить как позицию или смещение. Эта позиция нулевая.
В примере, если содержимое документа — последовательность "The quick brown fox", как показано на предшествующей диаграмме, расположение перед словом "The" равно 0, а расположение после слова "The" и перед последующим пробелом равно 3. Вся последовательность символов в последовательности "The" называется диапазоном.
Следующие методы предоставляют доступ к данным символов, составляющих содержимое.
Структура
Текст редко представляется просто как бесформенное содержимое. Скорее, текст, как правило, имеет связанную с ним структуру. То, какая структура моделируется, зависит от конкретной реализации документа. Это может быть так просто, как отсутствие структуры (т. е. простое текстовое поле), или что-то вроде диаграммы ниже.
Единицей структуры (т. е. узлом дерева) является интерфейс 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.
В модели документа API текста Swing интерфейс Element определяет структурный фрагмент документа, например, абзац, строку текста или элемент списка в HTML-документе.
Каждый элемент является либо ветвью, либо листом. Если элемент является ветвью, метод isLeaf() возвращает false. Если элемент является листом, isLeaf() возвращает true.
Ветки могут иметь любое количество дочерних элементов. Листья дочерних элементов не имеют. Чтобы определить, сколько дочерних элементов имеет ветвь, вы можете вызвать getElementCount(). Чтобы определить родительский элемент, вы можете вызвать getParentElement(). У корневых элементов нет родителей, поэтому вызов getParentElement() для корня возвращает null.
Элемент представляет собой определенную область в документе, которая начинается со startOffset и заканчивается непосредственно перед endOffset. Начальное смещение элемента ветви обычно совпадает с начальным смещением первого дочернего элемента. Аналогично, конечное смещение элемента ветви обычно совпадает с конечным смещением последнего дочернего элемента.
Каждый элемент связан с набором атрибутов, к которому можно получить доступ, вызвав getAttributes(). В элементе AttributeSet — это набор пар ключ/значение. Эти пары, как правило, используются для разметки — например, для определения цвета фона, размера шрифта элемента и т. д. Но модель и разработчик определяют, что хранится в AttributeSet.
Вы можете получить корневой элемент (или элементы) документа, вызвав методы getDefaultRootElement() и getRootElements(), определенные в интерфейсе Document.
Интерфейс Document отвечает за преобразование линейного представления символов в операции Element. Каждая реализация Document определяет, что такое структура Element.
Класс PlainDocument
Класс PlainDocument определяет структуру Element, в которой у корневого узла есть дочерние узлы для каждой строки текста в модели. На рисунке 1 показано, как две строки текста были бы смоделированы PlainDocument.
Рисунок 2 показывает, как эти те же две строки текста могут сопоставляться с фактическим содержимым:
Вставка текста в PlainDocument
Как уже упоминалось, PlainDocument содержит корневой элемент, который, в свою очередь, содержит элемент для каждой строки текста. Когда текст вставляется в PlainDocument, он создает необходимые элементы для существования элемента для каждого символа новой строки. Чтобы проиллюстрировать, предположим, что вы хотели вставить символ новой строки в смещении 2 на рисунке 2 выше. Для достижения этой цели можно использовать метод документа insertString(), используя такой синтаксис:
document.insertString(2, "\n", null); После вызова метода insertString() структура Element будет выглядеть так, как показано на рисунке 3.
В качестве другого примера, предположим, что вы хотите вставить шаблон "new\ntext\n" в смещении 2, как показано ранее на рисунке 2. Эта операция приведет к результату, показанному на рисунке 4.
На предыдущих иллюстрациях имя элементов строк изменяется после вставки, чтобы соответствовать номерам строк. Но обратите внимание, что при этом наборы атрибутов остаются неизменными. Например, на рисунке 2 набор атрибутов строки 2 соответствует набору атрибутов строки 4 на рисунке 4.
Удаление текста из PlainDocument
Удаление текста приводит к изменению структуры, если удаление охватывает более одной строки. Рассмотрим удаление семи символов, начиная со смещения 1, показанного ранее на рисунке 3. В этом случае элемент, представляющий строку 2, полностью удаляется, так как область, которую он представляет, находится в удаленной области. Элементы, представляющие строки 1 и 3, объединяются, так как они частично находятся в удаленной области. Таким образом, мы имеем результат:
Класс Default StyledDocument
Класс 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 someting 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, 2021, 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/17/docs/api/java.desktop/javax/swing/text/Document.html