Редактор объектов JFormattedTextField
Еще одно расширение класса JTextField- класс JFormattedTextField- предназначено
для работы с объектами, содержащими символы, такими как Date, Number. Впрочем, конструктор класса JFormattedTextField(Object) и метод setValue(Object) позволяют включить в редактор любой объект, при этом в окно редактирования будет выведен результат преобразования этого объекта в текстовую строку.
Типичное применение редактора:
JFormattedTextField ftf = new JFormattedTextField(new Date()); ftf.addActionListener(this);
// . . . . . . . .
// Редактируем дату... Потом нажимаем клавишу <Enter>
// . . . . . . . .
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=windows-1251",
"^Ш^Документ 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-тегом <img>. Но для работы с изображениями и компонентами более удобен редактор класса 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