При создании приложения с графическим интерфейсом очень часто приходится использовать поля для ввода текста. Такое поле может состоять из одной или нескольких строк, быть редактируемым или не редактируемым. В редактируемом окне часто приходится задавать возможность смены шрифта, цвета, вставку дополнительных символов. Библиотека Swing предоставляет для этого большие возможности, предлагая пакеты интерфейсов и классов javax.swing.text, javax.swing.text.html, j avax. swing.text. html .parser и j avax. swing. text. rtf.
РќР° вершине иерархии текстовых компонентов стоит класс JTextComponent — непосредственное расширение класса JComponent. Рто абстрактный класс, вобравший РІ себя общие свойства всех текстовых компонентов. РЈ него три расширения: однострочное текстовое поле JTextField, многострочная текстовая область JTextArea Рё небольшой, РЅРѕ мощный текстовый редактор JEditorPane, имеющий расширение- класс JTextPane, РјРµ
тодами которого можно оформить текст в каком-то определенном стиле.
У класса JTextField есть два расширения- поле для ввода пароля JPasswordField, в ко
тором вместо вводимых символов показывается один заранее определенный символ, по умолчанию звездочка, и поле для редактирования форматированных объектов JFormattedTextField, например даты — объекта класса Date, или чисел, заданных в определенном формате.
Рассмотрим текстовые компоненты подробнее и начнем с вершины их иерархии.
Компонент JTextComponent
Абстрактный класс JTextComponent стоит на вершине иерархии текстовых компонентов и содержит их общие свойства.
Текстовые компоненты построены по схеме "Model-View-Controller", которая отражена во внутреннем устройстве класса JTextComponent. Рассмотрим это устройство подробнее. Начнем с модели данных текстовых компонентов.
Модель данных — документ
Модель данных схемы MVC текстовых компонентов описана интерфейсом Document Рё называется документом. Документ может быть простым, "плоским", или сложным, структурированным. Рнтерфейс Document описывает простой текст (content), содержащийся РІ компоненте, как последовательность символов Unicode. Количество символов РІ тексте можно узнать методом getLength(). Последовательность символов нумеруется, начиная РѕС‚ нуля. Каждый СЃРёРјРІРѕР» имеет СЃРІРѕР№ порядковый номер, называемый позицией (position, location или offset) символа РІ тексте. Точнее РіРѕРІРѕСЂСЏ, модель данных задает позицию РЅРµ символа, Р° позицию между символами, перед текущим символом текста, что СѓРґРѕР±РЅРѕ для вставки текста.
Если текст документа сложный, структурированный, то, чтобы скрыть сложность определения текущей позиции РїСЂРё частых вставках Рё удалениях текста, СѓРґРѕР±РЅРѕ воспользоваться объектом, описанным интерфейсом Position. Ркземпляр класса, реализующего интерфейс Position, создается методом createPosition (int). Методы getStartPosition( ) Рё getEndPosition() возвращают начальную Рё конечную позиции текста РІ РІРёРґРµ объекта, реализующего интерфейс Position. Р’ интерфейсе Position всего РѕРґРёРЅ метод — getOffset (), возвращающий позицию символа РІ РІРёРґРµ целого числа типа int. РљСЂРѕРјРµ того, РІ интерфейсе Position есть вложенный класс Bias, РІ котором определены РґРІР° экземпляра класса Bias: поле Forward Рё поле Backward. РћРЅРё уточняют СЃРёРјРІРѕР», позиция которого определена: текущий или предыдущий. Позиция символа используется, например, РїСЂРё получении текста методами
String getText(int offset, int length);
void getText(int offset, int length, Segment text);
извлекающими из документа фрагмент текста длиной length символов, начиная от позиции offset. Второй метод заносит извлеченный фрагмент в экземпляр text класса Segment. Опишем этот небольшой, но удобный класс.
Строка символов Segment
Класс Segment представляет строку символов в виде, удобном для быстрого просмотра. У строки класса Segment всегда есть текущий символ, который можно получить методом current ( ). Позицию текущего символа можно узнать методом getIndex (), а установить — методом setIndex (int). Класс Segment содержит методы previous () и next (), возвращающие предыдущий и следующий символ строки, а также методы first () и last (), возвращающие первый и последний символ строки. Будьте внимательны: эти четыре метода меняют текущую позицию строки!
Рнтересно, что для быстроты доступа строка класса Segment хранится РІ открытом (public) поле — массиве СЃ именем array типа char [ ], начиная СЃ индекса offset, Рё занимает РІ этом массиве count элементов. Рто открытые поля, так что Рє массиву символов можно обращаться напрямую Рё менять его элементы, хотя РїСЂРё этом теряется главное назначение класса Segment- быстро просматривать текст. Метод getBeginIndex() РІРѕР·
вращает индекс начала строки в массиве array, т. е. число offset, а getEndIndex( ) индекс элемента массива, следующего за последним символом строки.
Заканчивая обзор класса Segment, скажем, что для большей надежности выполнения метода getText(int, int, Segment) в класс Segment введен метод setPartialReturn(boolean). Если в этом методе задать параметр true, то передача текста методом getText () в экземпляр класса Segment будет происходить, по возможности, без дополнительного копирования. Значение параметра по умолчанию — false. С учетом этого, работа с классом Segment начинается примерно так:
Segment seg = new Segment(); seg.setPartialReturn(true); doc.getText(0, doc.getLength(), seg);
// Работаем с объектом seg...
Запись текста в документ
Прежде чем использовать текст документа, его надо записать в документ. Запись выполняется методом
void insertString(int offset, String text, AttributeSet attr);
Новый текст text вставляется перед символом с позицией offset, позиция этого и следующих символов увеличивается на длину вставленного текста.
Атрибуты текста
Как видно из сигнатуры метода insertString(), у вносимого текста могут быть атрибуты, например: имя шрифта, размер шрифта, цвет. Если у текста нет атрибутов, то третьему параметру метода надо дать значение null.
Атрибуты записываются РІ РІРёРґРµ пар "РёРјСЏ — значение" РІ объект, реализующий интерфейс AttributeSet. Ртот интерфейс описывает неизменяемое множество атрибутов, РІ нем РЅРµ описаны методы добавления Рё удаления атрибутов. Такие методы внесены РІ его расширение — интерфейс MutableAttributeSet. Р’ библиотеке Swing есть реализация данного интерфейса — класс SimpleAttributeSet. РЎ помощью этого класса можно определить любые пары "РёРјСЏ — значение", РЅРѕ общепринятые атрибуты удобнее задавать СЃ использованием констант Рё статических методов класса StyleConstants Рё четырех его подклассов, которые РІ то же время вложены РІ него: CharacterConstants, ColorConstants, FontConstants Рё ParagraphConstants.
Объект, реализующий интерфейс AttributeSet, может содержать ссылку на другой, "родительский" объект того же типа. Ссылка хранится как значение атрибута, имеющего имя ResolveAttribute. Так можно получить цепочку объектов, содержащих атрибуты текста. Если какая-то пара "имя — значение" не найдена в первом объекте методом getAttribute (Object), то она отыскивается в родительском объекте, который определяется методом getResolveParent (), затем поиск идет далее по цепочке.
РЈ интерфейса MutableAttributeSet есть СЃРІРѕРµ расширение- интерфейс Style. Рто расши
рение дает возможность получить имя множества атрибутов методом getName ( ), создав так называемый стиль (style), и присоединить к множеству слушателя события
ChangeEvent методом
void addChangeListener(ChangeListener chl);
Заданное имя затем можно использовать как значение другого атрибута, а с помощью слушателя отслеживать добавление и удаление атрибутов.
Для создания стилей и работы с ними очень полезен класс StyleContext. Его экземпляр с общепринятым набором атрибутов можно получить следующим образом:
StyleContext stc = StyleContext.getDefaultStyleContext();
Затем в полученный объект stc можно добавить новые атрибуты методами addAttribute (), удалить атрибуты методами removeAttribute(), создать цепочку стилей.
Удаление текста из документа
Обратная операция — удаление части или всего текста из документа — выполняется методом
remove(int offset, int length);
Он удаляет length символов, начиная от символа, находящегося в позиции offset.
Фильтрация документа
Операции занесения текста РІ документ методом insertString() Рё удаления методом remove () можно изменить так, чтобы РѕРЅРё производили различные проверки Рё модификации, фильтруя таким СЃРїРѕСЃРѕР±РѕРј вставляемый или удаляемый текст. Рто можно сделать прямым расширением класса, реализующего Document, Рё переопределением его методов insertString () Рё remove (). РќРѕ есть еще РѕРґРёРЅ СЃРїРѕСЃРѕР±, РЅРµ изменяющий документ.
Сначала надо расширить класс DocumentFilter, переопределив его методы. В классе DocumentFilter всего три метода:
void insertString(DocumentFilter.FilterBypass fb, int offset,
String text, AttributeSet attr);
void remove(DocumentFilter.FilterBypass fb, int offset, int length); void replace(DocumentFilter.FilterBypass fb, int offset, int length,
String text, AttributeSet attr);
РС… стандартная реализация просто вызывает соответствующие методы вложенного абстрактного класса FilterBypass, которые оставлены абстрактными.
После расширения класса DocumentFilter, вызванного переопределением методов, полученный фильтр надо установить в документ методом
void setDocumentFilter(DocumentFilter filter);
класса AbstractDocument. Далее всякое обращение к методам insertString () и remove () документа будет пропускаться через методы созданного фильтра.
Пример использования фильтра, пропускающего только цифры, приведен в листинге 12.1.
Внесение структуры в документ
Р’ модель данных можно внести структуру дерева, например разбить документ РЅР° главы, параграфы, разделы. Каждый элемент разбиения описывается интерфейсом Element. Рлемент занимает какую-то область текста СЃ начальной позицией, возвращаемой методом getStartOffset (), Рё конечной позицией getEndOffset (). РЈ элемента может быть родительский элемент, который легко получить методом getParentElement(). Область текста, занимаемая родительским элементом, полностью включает РІ себя область РёСЃС…РѕРґРЅРѕРіРѕ элемента. РЈ элемента РјРѕРіСѓС‚ быть дочерние элементы, чья область текста полностью лежит внутри области самого элемента. РС… можно получить методом getElement(int). Число дочерних элементов возвращает метод getElementCount (), Р° индекс дочернего элемента — метод getElementIndex (int). Рлементу можно дать РёРјСЏ, Р° затем получить его методом getName ().
Рнтерфейс Element частично реализован абстрактным классом AbstractElement, вложенным РІ класс AbstractDocument, Рё полностью реализован еще РґРІСѓРјСЏ вложенными
в AbstractDocument классами — BranchElement и LeafElement, расширяющими класс AbstractElement. Основная разница между ними в том, что у класса BranchElement могут быть дочерние элементы, а у класса LeafElement — нет.
Класс BranchElement, в свою очередь, расширяется классом SectionElement, вложенным в класс DefaultStyledElement, и классом BlockElement, вложенным в класс HTMLDocument.
Класс LeafElement расширяется классом RunElement, вложенным РІ класс HTMLDocument. Рлементы создаются методами
Element createLeafElement(Element parent, AttributeSet attr,
int pos1, int pos2);
Element createBranchElement(Element parent, AttributeSet attr);
Для каждого структурного элемента можно задать свое множество атрибутов методом
addAttribute(Object name, Object value) или методом addAttributes(AttributeSet).
Р’ документе допускается задание нескольких независимых структур. РС… корневые элементы можно получить методом getRootElements ( ), возвращающим массив типа Element [ ]. РћРґРёРЅ РёР· корневых элементов можно сделать корневым элементом РїРѕ умолчанию Рё получать его методом getDefaultRootElement(), возвращающим элемент РІ РІРёРґРµ объекта, реализующего интерфейс Element. Получив корневые элементы структурного дерева, легко обойти его, используя метод getElement(int) интерфейса Element или метод children (), имеющийся РІ его реализациях.
События в документе
При всяком изменении документа или его структуры происходит событие, описанное интерфейсом DocumentEvent. Он предлагает метод getDocument ( ), позволяющий узнать, в каком документе произошло событие, методы getOffset () и getLength (), сообщающие о начальной позиции и длине измененного текста. Вложенный интерфейс ElementChange содержит метод getElement (), позволяющий узнать элемент, в котором произошло событие, и методы, помогающие отследить добавление и удаление элемента из документа.
Реализация интерфейса DocumentEvent — класс DefaultDocumentEvent, вложенный в класс AbstractDocument, — добавляет к методам интерфейса метод undo (), отменяющий изменения, метод redo (), восстанавливающий изменения, и еще несколько информационных методов.
Если модель данных позволяет отменять и восстанавливать изменения (undo/redo), то при каждом таком действии в ней происходит событие класса UndoableEditEvent.
Реализации документа
Рнтерфейс Document частично реализован абстрактным классом AbstractDocument. Ртот класс РІРЅРѕСЃРёС‚ понятие блокировки документа. Документ РјРѕРіСѓС‚ просматривать несколько подпроцессов-"читателей" Рё РѕРґРёРЅ подпроцесс-"писатель". Доступ РёС… Рє документу блокируется методами readLock() Рё writeLock(). Блокировки снимаются методами
readUnlock() Рё writeUnlock().
Класс AbstractDocument обычно не расширяется непосредственно, а используются или расширяются его подклассы PlainDocument и DefaultStyledDocument.
Класс PlainDocument задает модель простого документа с "плоским" текстом, которая используется полями ввода JTextField, JPasswordField, JTextArea. Текст в этой модели имеет структуру: структурные элементы текста — это строки. Корневой элемент структуры можно получить методом getDefaultRootElement(). Метод getParagraphElement(int offset) возвращает элемент структуры — строку в виде объекта типа Element, к которому принадлежит позиция offset. Каждой строке, как любому элементу структуры, можно придать атрибуты. Отдельные символы атрибутов не имеют.
Более сложную структуру вносит в документ модель класса DefaultStyledDocument, используемая в текстовом редакторе JTextPane. В этой модели не только строке, но и каждому символу текста можно задать свой стиль.
Наконец, класс DefaultStyledDocument расширяется классом HTMLDocument. Рто модель разметки языка HTML. Р’ ней можно определить таблицы стилей (style sheets).
Установка модели данных
После того как новая модель данных определена, ее надо установить в компонент методом setDocument(Document) класса JTextComponent.
Р’РёРґ
Вторая часть схемы MVC — Вид — построена для текстовых компонентов так, что для каждого элемента документа создается свой вид, значит, каждый элемент может получить свое графическое оформление.
Рта идея частично реализована абстрактным классом View. РћРЅ задает для каждого документа целую структуру Р’РёРґРѕРІ, отвечающую структуре элементов документа. Каждый РІРёРґ РёР· этой структуры РїСЂРё своем создании получает ссылку РЅР° определенный элемент документа, которую можно отследить методом getElement (). Документ, Рє которому относится Р’РёРґ, можно получить методом getDocument(). РЈ каждого Р’РёРґР° есть родительский РІРёРґ, который определяется методами getParent() Рё setParent ( ), Рё множество дочерних РІРёРґРѕРІ. РС… число можно определить методом getViewCount(), получить дочерние РІРёРґС‹ можно методом getView(int).
Создание дочерних Видов выполняется методом create(Element), описанным в интерфейсе ViewFactory. В документе у каждого элемента есть объект, реализующий этот интерфейс, который можно получить методом getViewFactory(). Еще несколько методов занимаются добавлением видов в иерархию и удалением их оттуда.
Каждый Р’РёРґ должен преобразовать линейный РїРѕСЂСЏРґРѕРє следования символов РІ элементе документа, определяемый РёС… позициями, РІ двумерное отображение символов РЅР° экран, состоящее РёР· нескольких строк экрана. Рто выполняется методом
Shape modelToView(int startPos, Position.Bias b0,
int endPos, Position.Bias b1, Shape fig);
который возвращает двумерную фигуру класса Shape. Параметры метода задают начальную startPos и конечную endPos позиции текста, направления b0 и b1 от этих позиций к преобразуемому тексту, которые могут принимать одно из двух значений:
Position.Bias.Backward или Position.Bias. Forward, и окружающую фигуру fig.
Обратное преобразование выполняется методом
int viewToModel(float x, float y, Shape fig, Position.Bias[] b);
возвращающим позицию символа, имеющего координаты (x, y) на экране в фигуре fig. Кроме того, метод вычисляет массив направлений b, уточняющий положение символа в модели данных.
Для вывода на экран в каждом виде создается графический контекст — экземпляр класса Graphics. Непосредственный вывод элемента на экран выполняется методом paint (Graphics) подобно выводу компонента. Графическим контекстом можно воспользоваться не только в методе paint(Graphics), но и непосредственно, получив его методом getGraphics ( ).
Каждый Вид устанавливает свой размер методом setSize(float width, float height), у него есть минимальный, предпочтительный и максимальный размер.
Р’ этом класс View напоминает класс Component. Сходство усиливается тем, что РїРѕРґРѕР±РЅРѕ тому, как класс Component порождает множество компонентов, создающих РЅР° экране графический интерфейс, класс View порождает множество подклассов-РІРёРґРѕРІ, отображающих РЅР° экране различные типы документов. РС… иерархия показана РЅР° СЂРёСЃ. 12.1.
Object
L View-г CompositeView— BoxView
PlainView
ImageView - IconView
-1— BlockView — ListView
— FlowView-ParagraphView
FieldView — TableView
L PasswordView — TableView.TableRow
— WrappedPlainView
— ZoneView
-GlyphView-LabelView—InlineView
-AsyncBoxView
- ComponentView-p FormView LobjectView
Р РёСЃ. 12.1. Рерархия классов-РІРёРґРѕРІ
Как видно из рис. 12.1, иерархия Видов обширна и разветвлена. Большинство классов связано с интерпретацией языка HTML, например класс ImageView обрабатывает тег
, класс FormView тег
Редактор объектов JFormattedTextField
Еще одно расширение класса JTextField- класс JFormattedTextField- предназначено
для работы с объектами, содержащими символы, такими как Date, Number. Впрочем, конструктор класса JFormattedTextField(Object) и метод setValue(Object) позволяют включить в редактор любой объект, при этом в окно редактирования будет выведен результат преобразования этого объекта в текстовую строку.
Типичное применение редактора:
JFormattedTextField ftf = new JFormattedTextField(new Date()); ftf.addActionListener(this);
// . . . . . . . .
// Редактируем дату... Потом нажимаем клавишу
// . . . . . . . .
public void actionPerformed(ActionEvent e){ newDate = (Date)ftf.getValue();
}
Метод getValue() возвращает объект типа Object, полученный в результате обратного преобразования отредактированной в окне строки в первоначальный объект.
Преобразованием объекта в строку и обратно занимается вложенный в JFormattedTextField абстрактный класс AbstractFormatter. Для этого в нем есть методы
valueToString(Object) Рё stringToValue(String). Рти методы оставлены абстрактными. После РёС… определения следует установить полученный "преобразователь" РІ редактор методом install (JFormattedTextField) класса AbstractFormatter или воспользоваться конструктором
JFormattedTextField(JFormattedTextField.AbstractFormatter);
или методом setFormatter(AbstractFormatter) класса JFormattedTextField.
Кроме преобразования объекта, AbstractFormatter определяет еще экземпляр класса
DocumentFilter Рё Ркземпляр класса NavigationFilter, которые можно получить методами
getDocumentFilter( ) Рё getNavigationFilter(). Рто придает редактору объектов вторую роль — проверять Рё фильтровать вводимый РІ поле текст, допуская только определенные символы.
В библиотеке Swing есть реализация класса AbstractFormatter — его расширение DefaultFormatter. Для преобразования объекта в строку метод valueToString (Obj ect) в классе DefaultFormatter определен очень просто: он использует метод toString () этого объекта. Метод stringToValue(string) обратного преобразования строки в объект использует конструктор класса с единственным параметром типа String. Если такого конструктора нет, то возвращается строка.
Класс DefaultFormatter применяется редко, он употребляется как базовый класс для полезных расширений. Несколько готовых расширений есть в библиотеке Swing.
От класса DefaultFormatter порождены два класса. Класс MaskFormatter определяет маску ввода, накладывающую ограничения на вводимые значения подобно классу Format и его подклассам из пакета java.text. Например, класс
MaskFormatter mf = new MaskFormatter("###.##");
накладывает маску действительных чисел с двумя знаками после десятичной точки.
Второй класс InternationalFormatter прямо использует класс Format для своих преобразований, который задается в конструкторе
InternationalFormatter(Format);
Он расширен двумя классами: класс NumberFormatter использует класс DecimalFormat для фильтрации чисел, а класс DateFormatter-класс DateFormat для отбора даты и времени.
Для того чтобы облегчить создание классов -преобразователей, в классе
JFormattedTextField есть вложенный абстрактный класс AbstractFormatterFactory, расширенный классом DefaultFormatterFactory. Ртот класс содержит несколько методов getXxxFormatter (), возвращающих тот или РёРЅРѕР№ объект-преобразователь.
Область ввода JTextArea
Класс JTextArea представляет многострочную область ввода с "плоским" текстом, в котором не меняются атрибуты шрифта. Для редактирования сложного текста удобнее использовать JTextEditor или JTextPane.
В область ввода JTextArea не заложена возможность прокрутки большого текста. Если в этом есть необходимость, то область надо поместить в контейнер JScrollPane:
JTextArea ta = new JTextArea(5, 50);
JScrollPane sp = new JScrollPane(ta); container.add(sp);
При этом следует задать размеры области — число строк и столбцов — как это сделано ранее, или предпочтительный размер JScrollPane.
РџРѕ умолчанию слово, РЅРµ поместившееся РІ РІРёРґРёРјРѕР№ части строки, РЅРµ переносится целиком РЅР° следующую строку. Рту возможность надо включить методом
setWrapStyleWord(true).
Аналогично, по умолчанию весь текст в области показывается в виде одной строки, выходящей за пределы окна. Если область ввода помещена в контейнер JScrollPane, то появляется горизонтальная линейка прокрутки. Чтобы строки не выходили за пределы окна, надо включить перенос строк методом setLineWrap(true).
Текст в область ввода можно не только занести методом setText(String), но и добавить в конец уже имеющегося текста методом append (String) и вставить программно в определенную позицию методом insert(String, int).
Область ввода допускает изменение размера табуляции методом setTabsize (int).
В остальном область ввода ведет себя как поле ввода класса JTextField.
Текстовый редактор JEditorPane
Текстовый редактор класса JEditorPane по умолчанию распознает три MIME-типа текста: text/plain, text/html и text/rtf, вызывая для изменения редакторы DefaultEditorKit, HTMLEditorKit или RTFEditorKit соответственно. Для того чтобы учесть MIME-тип текста, применяется конструктор
JEditorPane(String type, String text);
Он вызывает метод setContentType (type), задающий MIME-тип текста, а затем — метод
setText(text). Например:
JEditorPane ep= new JEditorPane("text/html;Content-Type=utf-8",
"^Ш^Документ HTML" );
JScrollPane sp = new JScrollPane(ep); container.add(sp);
Метод setText (String) не меняет выбранный редактор. Поэтому MIME-тип его параметра должен соответствовать имеющемуся редактору. Впрочем, можно установить новый редактор методом setEditor(EditorKit). Следует учитывать, что при этом сменится и документ!
Для определенного MIME-типа методом
setEditorKitForContentType(String type, EditorKit editor);
можно задать редактор, который будет вызываться для обработки текста этого типа.
Еще два конструктора позволяют занести начальный текст в редактор прямо с адреса, заданного в форме URL. Адрес задается объектом класса url или одной из строк:
JEditorPane(URL url);
JEditorPane(String url);
Рнформацию СЃ адреса URL можно занести РІ редактор РІ любое время методом setPage(url) или setPage(string url). Учтите, что РїСЂРё изменении MIME-типа текста поменяется тип документа Рё редактора. Если занесена страница HTML, то Р±СѓРґСѓС‚ установлены модель данных класса HTMLDocument Рё редактор класса HTMLEditorKit.
Самый общий способ загрузки текста — занести текст из входного потока методом
read(InputStream in, Object obj). Если установлен редактор HTMLEditorKit и параметр obj имеет тип HTMLDocument, то текст HTML будет проинтерпретирован. В других случаях будет обрабатываться "плоский" текст.
Текстовый редактор показывает и изображения, определенные HTML-тегом . Но для работы с изображениями и компонентами более удобен редактор класса JTextPane.
Редактор JTextPane
Класс JTextPane непосредственно расширяет класс JEditorPane и наследует все его свойства. Кроме этого он позволяет работать со структурированным текстом с различными стилями, поскольку по умолчанию наделен моделью данных типа
DefaultStyledDocument.
В редактор легко добавить новые стили методом
addStyle(String name, Style parent);
Можно задать множество атрибутов для отдельных символов, которые выделены в тексте или которые будут вводиться в текст, методом
setCharacterAttributes(AttributeSet attr, boolean replace);
Можно задать атрибуты сразу целому элементу, который выделен или в котором находится текущая позиция, методом
setParagraphAttributes(AttributeSet attr, boolean replace);
Если второй аргумент этих методов равен true, то существующие атрибуты будут заменены новыми.
Можно задать и новую модель данных методом
setStyledDocument(StyledDocument);
Редактор позволяет вставить в текущую позицию текста изображение методом insertIcon(Icon). Если часть текста была выделена, то изображение будет вставлено вместо выделенного текста.
Более того, РІ текущую позицию текста или вместо выделенного текста можно вставить любой компонент методом insertComponent(Component). Рзображение Рё компонент хранятся РІ модели данных как атрибут РѕРґРЅРѕРіРѕ символа.
Вопросы для самопроверки
1. Как используется модель MVC в текстовых компонентах?
2. В чем отличие текстовых компонентов Swing от аналогичных компонентов AWT?
3. Можно ли в текстовых компонентах Swing менять шрифт?
4. Можно ли в текстовых компонентах Swing использовать разные шрифты в одной строке?
5. В каких случаях удобно использовать готовые текстовые редакторы Swing?
6. Можно ли средствами Swing написать свой текстовый редактор Swing?
7. Можно ли в текстовых редакторах Swing использовать разные шрифты в одном документе?
ГЛАВА 13