480 |
ГЛАВА 16 |
рой), а частично реализован в виде карты клавиатуры (keymap), аналога карты входных событий, известной нам еще с главы 5. Карта клавиатуры позволяет гибко, без смены UI-представителя текстового компонента, менять реакцию текстового компонента на нажатия клавиш (это очень важно, поскольку даже в одном текстовом компоненте могут поддерживаться несколько видов документов, способы редактирования которых возможно кардинально отличаются) и таким образом представляет собой ограниченный вариант контроллера.
Тем не менее, для будничной работы с текстовыми компонентами, за рамки которой большинство приложений не выходит, нам не придется вникать в детали реализации текстового пакета и тонко настраивать его механизмы. Познакомимся теперь с текстовыми компонентами Swing и убедимся, что работать с ними не сложнее, чем с другими компонентами библиотеки.
Каталог текстовых компонентов
Как мы уже отмечали, Swing предоставляет нам целый арсенал текстовых средств, от небольших полей для ввода простого текста до полнофункциональных редакторов со всеми мыслимыми возможностями. Прежде чем перейти к более детальному изучению их возможностей (большинство из которых для всех текстовых компонентов одинаковы), составим своеобразный каталог текстовых компонентов Swing с небольшими примерами, которые позволят нам быстро познакомиться с ними. Кроме того, данный каталог удобно будет держать «под рукой» в качестве простого справочника.
Текстовые поля
Текстовые поля (text fields) — самые простые и наиболее часто встречающиеся в пользовательских интерфейсах текстовые компоненты. Как правило, такое поле является однострочным и служит для ввода текста. В библиотеке Swing имеется два текстовых поля. Первое, представленное классом JTextField, позволяет вводить некоторый простой однострочный текст (разнообразные атрибуты форматирования, такие как дополнительные цвета и шрифты, не поддерживаются). Второе поле, реализованное классом JPasswordField и унаследованное от простого поля JTextField, дает возможность организовать ввод «секретной» информации (чаще всего паролей), которая не должна напрямую отображаться на экране. Оба текстовых поля очень просты, работа с ними чаще всего сводится к заданию количества отображаемых в поле символов и начального текста (если таковой требуется), после чего остается только поместить поле в контейнер и в нужный момент получить из него набранный пользователем текст. Рассмотрим простой пример использования текстовых полей Swing:
//UsingTextFields.java
//Использование текстовых полей Swing import javax.swing.*;
import java.awt.*; import java.awt.event.*;
public class UsingTextFields extends JFrame { // наши поля
private JTextField smallField, bigField; public UsingTextFields() {
super("UsingTextFields");
Текстовые компоненты |
481 |
setDefaultCloseOperation(EXIT_ON_CLOSE);
//создаем текстовые поля smallField = new JTextField(10);
bigField = new JTextField("Текст поля", 25);
//дополнительные настройки
bigField.setFont(new Font("Verdana", Font.PLAIN, 16)); bigField.setHorizontalAlignment(JTextField.RIGHT);
// слушатель окончания ввода smallField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { // показываем введенный текст
JOptionPane.showMessageDialog(
UsingTextFields.this, "Ваше слово: " +
smallField.getText());
}
}); // поле с паролем
JPasswordField password = new JPasswordField(15); password.setEchoChar('$');
// добавляем поля в окно и выводим его на экран setLayout(new FlowLayout());
add(smallField);
add(bigField);
add(password); setSize(400, 300); setVisible(true);
}
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new UsingTextFields(); } });
}
}
Здесь мы создаем окно небольших размеров с несколькими текстовыми полями. Первое поле создается с помощью наиболее распространенного варианта конструктора класса JTextField, которому необходимо передать максимальное количество символов в поле. Для однострочных текстовых полей прокрутка не нужна, и размер поля (в символах) должен примерно соответствовать объему информации, которую пользователь вводит в поле. В противном случае работать с текстовым полем было бы не совсем удобно, причем как при нехватке места для вводимой информации, так и при избыточной длине поля. В нашем примере особенных требований к вводимой информации нет, так что мы вполне можем указать произвольное количество символов. Второе поле созда-
482 |
ГЛАВА 16 |
ется более функциональным конструктором: ему необходимо передать текст, который будет записан в поле, и максимальное количество символов (для примера мы делаем это значение достаточно большим). Далее демонстрируются дополнительные возможности текстовых полей, довольно примитивные, но вполне уместные: вы можете с легкостью сменить шрифт и вариант выравнивания текста в поле (по умолчанию текст выравнивается по левому краю, мы выровняли его по правому краю, таким же образом можно задать выравнивание текста по центру).
Обратите внимание на то, что к текстовому полю можно присоединить слушателя событий ActionListener. Такие слушатели оповещаются о нажатии пользователем специальной клавиши, сигнализирующей об окончании ввода (обычно это клавиша Enter). Использовать слушателя особенно удобно в случае текстовых полей, предназначенных для ввода важной информации, такой как имя пользователя в диалоговом окне входа в систему. Присоединение к полю слушателя ActionListener ускоряет процесс работы с интерфейсом, так как избавляет пользователя от необходимости каждый раз по окончании ввода данных щелкать на подтверждающих кнопках (подобных кнопке OK) — вместо этого он сразу же, не покидая текстового поля, нажимает клавишу Enter и быстро переходит к следующему этапу работы с приложением. Помимо прямого присоединения к полю слушателя ActionListener вы можете воспользоваться методом setAction(), присоединяющего к полю объект-команду Action (применение этого метода не удаляет уже присоединенных к полю слушателей, все они также будут оповещаться о завершении ввода).
Пример также иллюстрирует работу с полем для ввода «секретных» данных JPasswordField. Не забывайте, что данное поле унаследовано от обычного поля JTextField, так что все вышесказанное верно и для него. Из собственных методов поля JPasswordField можно упомянуть лишь метод setEchoChar(), служащий для смены символа-заменителя (символа, который отображается вместо всех вводимых пользователем в поле символов во избежание появления на экране конфиденциальной информации). По умолчанию в качестве такого символа используется звездочка (*), которую для примера мы заменили символом доллара ($). Разработчики класса JPasswordField не рекомендуют также применять для получения введенного в поле значения (пароля) обычный метод getText(). Дело в том, что создаваемая данным методом строка String не может меняться все время жизни программы (объекты String в Java максимально оптимизируются компилятором и виртуальной машиной), и вы не сможете «стереть» ее из памяти. Для получения данных предоставляется более безопасный метод getPassword(), возвращающий массив символов char (значения которого после проверки имеет смысл обнулить и при желании вызвать сборщик мусора). Поле JPasswordField также особым образом копирует данные в буфер обмена — оно переопределяет методы cut() и copy() (эти методы определены в базовом классе JTextComponent), запрещая копировать набранный текст в буфер обмена, что также служит для защиты конфиденциальной информации.
Запустив программу с примером, вы сможете увидеть работу текстовых полей воочию. Подвести итог нам поможет табл. 16.1 с описанием основных свойств текстовых полей Swing.
Текстовые компоненты |
483 |
|
Таблица 16.1. Свойства текстовых полей |
|
|
|
|
|
Свойства |
Описание |
|
(и методы get/set) |
|
|
text |
Позволяет получить введенный в поле текст или заменить его. Для по- |
|
|
ля с конфиденциальной информацией лучше использовать метод |
|
|
getPassword() |
|
columns |
Задает количество столбцов в поле, так что вы можете получить размер |
|
|
поля или в любой момент изменить его |
|
font |
Определяет используемый в текстовом поле шрифт. Не стоит слишком |
|
|
вольно распоряжаться этим свойством, так как текстовые поля встреча- |
|
|
ются в интерфейсе часто и должны органично вливаться в общий стиль |
|
|
внешнего вида приложения. Экзотичные шрифты, особенно больших раз- |
|
|
меров, могут этому помешать |
|
horizontalAlignment |
Управляет выравниванием текста в поле. По умолчанию текст выравни- |
|
|
вается по левой границе поля, вы можете выбрать для текста любой из |
|
|
трех вариантов выравнивания (слева, справа или по центру) |
|
echoChar (только для |
Задает символ-заменитель для ввода секретной информации. По умол- |
|
класса JPassword- |
чанию используется символ звездочки (*) |
|
Field) |
|
|
И еще одно замечание: если вы помните, в главе 7 при изучении блочного расположения BoxLayout мы столкнулись с неприятной проблемой, связанной с текстовым полем JTextField: при использовании менеджера расположения, учитывающего максимальный размер компонентов, поле «раздувается», так как максимальный размер его не ограничен. Свойства неограниченности максимального размера унаследовано классом JTextField от своего предка JTextComponent. Для всех остальных текстовых компонентов оно подходит как нельзя лучше — вы можете вводить в такие компоненты неограниченное количество символов текста (все упирается только в доступную вашему приложению память), но для однострочных полей JTextField и JPasswordField это не так. В рассмотренном нами примере использовалось последовательное расположение FlowLayout (в панелях JPanel оно устанавливается по умолчанию), в котором учитывается только предпочтительный размер компонента, так что с ним вопросов не возникает. Ну а трудности с другими менеджерами расположения мы решили в главе 7, написав для исправления размера текстового поля вспомогательный инструмент.
Многострочное поле JTextArea
Многострочное текстовое поле JTextArea представляет собой немного более расширенную версию обычного текстового поля JTextField (хотя класс JTextArea не унаследован от класса JTextField, слишком уж различна их реализация). Как и обычное поле JTextField, многострочное поле JTextArea предназначено для ввода простого неразмеченного различными атрибутами текста, но в отличие от обычных полей, позволяющих вводить только одну строку текста, многострочные поля дают пользователю возможность вводить произвольное количество строк текста. Кроме того, поле JTextArea часто используется для вывода разного рода подробной информации о работе приложения, отображать которую в диалоговых окнах или в консоли неудобно. Вывод информации в многострочное текстовое поле позволяет пользователю без труда просмотреть ее, как бы много ее ни было, и при необходимости скопировать или изменить.
Работают с многострочными полями так же, как с обычными, за тем исключением, что для них приходится задавать не только ширину (максимальное количество символов), но и высоту (максимальное количество строк). Многострочные текстовые поля
484 |
ГЛАВА 16 |
следует размещать в панелях прокрутки JScrollPane, иначе при вводе множества строк текста они «расползутся» по контейнеру и испортят вид остальных компонентов. Рассмотрим несложный пример и познакомимся с основными возможностями класса
JTextArea:
//UsingTextArea.java
//Использование многострочных полей import javax.swing.*;
import java.awt.*;
public class UsingTextArea extends JFrame { public UsingTextArea() {
super("UsingTextArea"); setDefaultCloseOperation(EXIT_ON_CLOSE);
//создаем пару многострочных полей
JTextArea area1 = new JTextArea( "Многострочное поле", 5, 10);
//нестандартный шрифт и табуляция area1.setFont(new Font("Dialog", Font.PLAIN, 14)); area1.setTabSize(10);
JTextArea area2 = new JTextArea(15, 10);
//параметры переноса слов area2.setLineWrap(true); area2.setWrapStyleWord(true);
//добавим поля в окно
setLayout(new FlowLayout()); add(new JScrollPane(area1)); add(new JScrollPane(area2)); // выводим окно на экран setSize(400, 300); setVisible(true);
}
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new UsingTextArea(); } });
}
}
В примере мы размещаем в окне пару многострочных текстовых полей JTextArea, для которых были изменены некоторые наиболее интересные свойства, чаще других использующиеся в приложениях. Первое текстовое поле создается с помощью довольно функционального конструктора, задающего для поля находящийся в нем текст, количество строк и символов. Обратите внимание, что количество строк идет в списке параметров перед количеством символов; здесь часто возникает путаница, так как для