
Портянкин И. Swing
.pdf
Стандартные диалоговые окна |
415 |
пустая строка. Если же пользователь отменил ввод щелчком на кнопке Cancel4, методы showInputDialog() вернут вам пустую (null) ссылку.
Вторая кнопка выводит на экран диалоговое окно, также получающее данные с помощью текстового поля; для его создания вам понадобится четыре параметра. Первые два параметра будут такими же, как и для только что рассмотренных диалоговых окон — это родительский компонент и сообщение (отметьте, кстати, что ради разнообразия мы записали сообщение массивом строк), в вот вторые два для нас внове. Третьим параметром является заголовок создаваемого диалогового окна, а четвертым — его тип (см. табл. 14.1). По умолчанию в методах showInputDialog() используются тип QUESTION_ MESSAGE и соответствующий стандартный значок, но, как видите, сменить его можно. В примере показано вполне реальное применение этой возможности: вы можете повысить уровень «опасности» диалогового окна для ввода данных (таким окном может быть, например, окно для ввода паролей).
Создаваемые с помощью первых двух кнопок диалоговые окна обеспечивают ввод данных с помощью текстовых полей, а вот третья кнопка иллюстрирует кое-что необычное — выбор варианта из нескольких известных альтернатив. Тут же вспоминается раскрывающийся список JComboBox, как раз и позволяющий выбирать из нескольких альтернатив. И на самом деле, класс JOptionPane использует для этой почетной миссии именно его. Правда, создание диалогового окна для такого выбора требует дополнительных хлопот: придется указывать целых семь параметров. Первые четыре нам знакомы — все тот же родительский компонент, сообщение, заголовок окна и его тип. Далее следует значок, вы можете и не задавать его, передав вместо него пустую (null) ссылку, в таком случае будет использован стандартный значок. Наконец, последние два параметра ведают непосредственно выбором — это массив доступных альтернатив (и в нем вы можете задействовать «вездесущий» язык HTML) и элемент, выбранный изначально. Запустив программу с примером и щелкнув на третьей кнопке, вы оцените, как работает данный вариант стандартного диалогового окна. Кстати, возвращается в этом случае выбранный элемент, один из тех, что вы передали ему в качестве доступных альтернатив, или null, если пользователь щелкнул на кнопке Cancel. Для демонстрации этого мы тут же, сразу после выбора, показываем выбранный элемент уже знакомым нам методом showMessageDialog().
4 «А как же локализованные приложения?» — спросите вы: «Можно ли изменять надписи на кнопках в стандартных диалоговых окнах?». Конечно, сделать это можно, и довольно просто. Надписи для кнопок UI-представитель извлекает из специальной таблицы с параметрами внешнего вида, UIDefaults. Получить доступ к этой таблице, то есть получить используемые в данный момент надписи или сменить их, позволяют особые методы get/set класса UIManager. К примеру, заменить кнопку Cancel кнопкой Отмена позволит строка UIManager.put(«OptionPane. cancelButtonText», «Отмена»).

416 |
ГЛАВА 14 |
В примере были представлены не все доступные варианты метода showInputDialog(). Так, варианты этого метода, используемые при щелчке на первой кнопке, могут быть еще проще — создаваемые диалоговые окна не требуют передачи ссылок на родительские компоненты и размещаются по центру рабочего стола пользователя. Но такой же эффект можно получить, передавая вместо родительских компонентов ссылки null, так что мы ничего не упустили.
Получение подтверждений
Следующая группа статических методов класса JOptionPane с общим названием showConfirmDialog() служит для вывода на экран стандартных диалоговых окон, запрашивающих у пользователя разрешение на совершение некоторого действия. Как правило, это запрос вида «Вы действительно хотите удалить файл?», который класс JOptionPane снабжает парой кнопок Да и Нет. Можно прибавить к этим трем кнопкам и кнопку отмены. Получив от пользователя положительный ответ, вы вправе считать, что он понимает последствия совершаемого действия и согласен на него. Рассмотрим несложный пример, в котором изучим все варианты метода showConfirmDialog():
//ConfirmDialogs.java
//Стандартные диалоговые окна для получения от
//пользователя подтверждения совершаемого действия import javax.swing.*;
import java.awt.event.*; import java.awt.*;
public class ConfirmDialogs extends JFrame { // значок для одного из сообщений
private Icon icon = new ImageIcon("goblet.png"); public ConfirmDialogs() {
super("ConfirmDialogs"); setDefaultCloseOperation(EXIT_ON_CLOSE);
// после щелчков на кнопках выводятся сообщения
JButton confirm1 = new JButton("2 и 4 параметра"); confirm1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {
// диалоговое окно c 4-мя параметрами int res = JOptionPane.showConfirmDialog(
Стандартные диалоговые окна |
417 |
ConfirmDialogs.this, "Вы этого хотите?", "Вопрос", JOptionPane.YES_NO_CANCEL_OPTION);
// простейшие диалоговые окна
if ( res == JOptionPane.YES_OPTION ) JOptionPane.showConfirmDialog(
ConfirmDialogs.this, "Точно хотите?"); if ( res == JOptionPane.NO_OPTION )
JOptionPane.showConfirmDialog( ConfirmDialogs.this, "Значит, не хотите?");
}
});
JButton confirm2 = new JButton("5 параметров"); confirm2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int res = JOptionPane.showConfirmDialog(
ConfirmDialogs.this,
"Думайте тщательно, итак...", "Может произойти ошибка!", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE);
}
});
JButton confirm3 = new JButton("6 параметров"); confirm3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int res = JOptionPane.showConfirmDialog(
ConfirmDialogs.this, "Вам нравится значок?", "Полностью настроенное окно!", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, icon);
}
});
//добавляем кнопки в окно setLayout(new FlowLayout()); add(confirm1);
add(confirm2); add(confirm3);
//выводим окно на экран setSize(300, 200);

418 ГЛАВА 14
setVisible(true);
}
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new ConfirmDialogs(); } });
}
}
В примере мы создаем небольшое окно с рамкой JFrame, в котором разместятся три кнопки. Щелкая на этих кнопках, вы будете вызывать на экран стандартные диалоговые окна, созданные различными вариантами метода showConfirmDialog() класса
JOptionPane.
Первая кнопка демонстрирует сразу два вида диалоговых окон, созданных самыми простыми вариантами метода с названием showConfirmDialog(). Для начала на экране появляется диалоговое окно, созданное методом, принимающим четыре параметра — это родительский компонент, сообщение для отображения (в качестве сообщения могут выступать любые объекты, перечисленные нами в табл. 14.2, или массив таких объектов), заголовок окна, а также константа из класса JOptionPane, указывающая, набор каких альтернатив будет представлен пользователю для выбора (эти альтернативы появятся внизу диалогового окна в виде набора кнопок). Константы, которые обычно применяются для диалоговых окон, создаваемых методом showConfirmDialog(), перечислены в табл. 14.3.
Таблица 14.3. Константы класса JOptionPane, задающие набор альтернатив для диалоговых окон, запрашивающих подтверждение
Константа Описание
YES_NO_CANCEL_OPTION Этот набор альтернатив по умолчанию применяется в диалоговых
окнах, создаваемых методом showConfirmDialog(). При использова-
нии данного набора в окне появляются кнопки Да, Нет и Отмена
YES_NO_OPTION Набор альтернатив практически идентичен предыдущему за одним исключением — в окне не будет кнопки Отмена
OK_CANCEL_OPTION При использовании этого набора альтернатив в диалоговом окне вме-
сто кнопок Да и Нет появятся кнопки ОК и Отмена
Как правило, вариант метода showConfirmDialog() с четырьмя параметрами применяется в программах чаще остальных: он сочетает в себе легкость и полноту настройки с простотой вызова. Значения, которые могут возвращать варианты метода showConfirmDialog(), перечислены в табл. 14.4.
Таблица 14.4. Значения, возвращаемые методом showConfirmDialog()
Значение |
Описание |
YES_OPTION (OK_OPTION) Это значение возвращается, если пользователь подтвердил свое на- |
|
|
мерение произвести некоторое действие, щелкнув на соответствую- |
|
щей кнопке (Да или ОК) |
NO_OPTION |
Это значение вы получите в том случае, если пользователь отказался |
|
от своего намерения, щелкнув на кнопке Нет |

Стандартные диалоговые окна |
419 |
|
Таблица 14.4 (продолжение) |
|
|
|
|
|
Значение |
Описание |
|
CANCEL_OPTION |
Первое значение возвращается, если пользователь |
не пожелал |
(CLOSED_OPTION) |
в данный момент отвечать на вопрос диалогового окна, щелкнув на |
|
|
кнопке Отмена. Второе значение показывает, что пользователь про- |
|
|
сто закрыл диалоговое окно. Как правило, этот вариант ничем не от- |
|
|
личается от отмены |
|
В примере мы проверяем, какой выбор сделал пользователь, и в зависимости от него предлагаем еще одно диалоговое окно с окончательным подтверждением сделанного выбора. Второе диалоговое окно создается самым лаконичным вариантом метода showConfirmDialog(): он принимает всего два параметра: родительский компонент (вы можете указать и пустую ссылку null, в этом случае диалоговое окно будет размещено по центру главного окна или рабочего стола пользователя, в зависимости от версии JDK) и само сообщение. В качестве набора альтернатив такого окна будет использован набор
YES_NO_OPTION. Заметьте, параметры для метода showConfirmDialog() класса JOptionPane
идентичны параметрам других уже рассмотренных нами методов данного класса, что без сомнения облегчает работу с ними.
Вторая кнопка демонстрирует, как выглядит диалоговое окно для получения подтверждения, созданное методом showConfirmDialog() с пятью параметрами. Первые четыре параметра неизменны, а в пятом параметре вы сможете указать тип диалогового окна; доступные типы стандартных диалоговых окон мы уже описали в табл. 14.1. В примере мы создаем диалоговое окно для получения подтверждения пользователя, одновременно (с помощью пятого параметра) придавая ему стиль окна, сообщающего об ошибке. В некоторых ситуациях подобная комбинация способна лучше выразить важность задаваемого пользователю вопроса, нежели простая форма диалогового окна.
Ну и наконец, самая полная форма метода showConfirmDialog(), с шестью параметрами, практически ничем не отличается от формы с пятью параметрами, за исключением именно шестого параметра — это значок Icon, который будет отображен в диалоговом
420 |
ГЛАВА 14 |
окне взамен стандартного значка, поставляемого вместе с текущими внешним видом и поведением Swing.
Запустив программу с примером, вы воочию увидите, как стандартные диалоговые окна JOptionPane позволяют получать от пользователя подтверждение о проведении дальнейших действий, и сможете применять их в собственных программах, так что ваш пользователь не останется в неведении.
Дополнительные возможности
Чаще всего класс JOptionPane применяется так, как мы использовали его в рассмотренных примерах: вы вызываете один из многочисленных статических методов, выводящих на экран стандартное диалоговое окно, не забывая передать в метод список подходящих параметров, полностью определяющих внешний вид будущего окна. Но у класса JOptionPane имеются и другие достоинства. Прежде всего это способность работать в виде самого обыкновенного компонента: вы создаете объект класса JOptionPane, используя при этом подходящий конструктор, настраиваете остальные свойства с помощью методов get/set (а свойствами класса являются все свойства диалоговых окон, прежде задаваемых нами в виде параметров статических методов, в том числе тип сообщения, само сообщение, значок и т. п.), а затем выводите полученный компонент на экран так, как вам угодно (к примеру, в диалоговом окне, созданном своими руками, если вам это необходимо). Создание компонента имеет свои преимущества: вы получаете больший контроль над тем, где и когда появляются стандартные диалоговые окна, а также экономию памяти — стандартные диалоговые окна одного вида и предназначения могут создаваться один раз, меняться будут лишь текст сообщения и заголовок окна.
Далее можно использовать те методы showXXXDialog(), которые мы изучили в данной главе, а также методы с общим названием showInternalXXXDialog(). В последнем случае стандартные диалоговые окна появляются в специальном компоненте Swing с названием JDesktopPane, предназначенном для создания приложений с многодокументным интерфейсом (MDI). Но чтобы методы showInternalXXXDialog() работали, необходима поддержка в вашем приложении многодокументного интерфейса и рабочего стола (компонента JDesktopPane), а это, учитывая все снижающуюся популярность многодокументного интерфейса, встречается уже не так часто, к тому же в таком виде стандартные диалоговые окна привлекают к себе недостаточно внимания. Поэтому в подавляющем большинстве случаев вполне хватает изученных нами методов (и в большинстве случаев они лучше соответствуют нуждам приложений).
Помимо рассмотренных нами методов showXXXDialog(), предназначенных для вывода сообщений, ввода несложных данных и получения подтверждений, в классе JOptionPane имеется еще один метод с названием showOptionDialog(). С его помощью вы можете вывести на экран любое сообщение, разместить в нем любые компоненты и снабдить его нужными типом и набором альтернатив для выбора. Вот только метод этот довольно громоздкий, и, если вам потребуется совершенно особое диалоговое окно с необычным набором компонентов, лучше это диалоговое окно создать «с нуля», и заполнить компонентами окно JDialog.
Выбор файлов в компоненте JFileChooser
Выбор файлов необходим в любом более или менее приличном приложении: в самом деле, все, что пользователями делается, чаще всего сохраняется в файлах, даже если расположены они на удаленных серверах. Компонент JFileChooser — отличный и легко настраиваемый инструмент для выбора файлов и при необходимости каталогов. Особенности различных файловых систем скрыты в подклассах абстрактного

Стандартные диалоговые окна |
421 |
класса FileSystemView, и беспокоиться вам об |
этих различиях не придется: выбранный |
вами для приложения внешний вид отобразит файловую структуру как подобает -- соответственно текущей операционной системе5. В самом начале главы мы упомянули, что JFileChooser — это обычный компонент, унаследованный от класса JComponent, так что вы можете включить его в любое место своего интерфейса. Так оно и есть, но удобнее использовать пару методов, показывающих компонент для выбора файлов в собственном модальном диалоговом окне. Настроить и вывести на экран несложное диалоговое окно для открытия файла или сохранения в нем данных совсем легко. Рассмотрим пример:
//SimpleFileChooser.java
//Создание простых диалоговых окон
//открытия и сохранения файлов import javax.swing.*;
import java.awt.event.*; import java.awt.*;
public class SimpleFileChooser extends JFrame { // создадим общий экземпляр JFileChooser private JFileChooser fc = new JFileChooser(); public SimpleFileChooser() {
super("SimpleFileChooser"); setDefaultCloseOperation(EXIT_ON_CLOSE);
// кнопка, создающая диалоговое окно для открытия файла
JButton open = new JButton("Открыть..."); open.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { fc.setDialogTitle("Выберите каталог");
//настроим для выбора каталога fc.setFileSelectionMode(
JFileChooser.DIRECTORIES_ONLY); int res = fc.showOpenDialog(
SimpleFileChooser.this);
//если файл выбран, покажем его
if ( res == JFileChooser.APPROVE_OPTION ) JOptionPane.showMessageDialog(
SimpleFileChooser.this,
fc.getSelectedFile());
}
});
5 Все операционные системы поддерживаются только одним стандартным внешним видом, поставляющимся вместе с JDK, — внешним видом Metal, который используется в Swing по умолчанию. Остальные внешние виды могут показывать только соответствующую файловую систему. Так что запускать под Windows программу с внешним видом CDE или Motif можно, но вот выбирать файлы в ней будет затруднительно — файловая система Unix для Windows не слишком подходит.
422 |
ГЛАВА 14 |
//кнопка, создающая диалоговое окно
//для сохранения файла
JButton save = new JButton("Сохранить..."); save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { fc.setDialogTitle("Сохранение файла");
//настройка режима fc.setFileSelectionMode(
JFileChooser.FILES_ONLY); int res = fc.showSaveDialog( SimpleFileChooser.this);
//сообщим об успехе
if ( res == JFileChooser.APPROVE_OPTION ) JOptionPane.showMessageDialog(
SimpleFileChooser.this, "Файл сохранен");
}
}); // добавим кнопки и выведем окно на экран
setLayout(new FlowLayout()); add(open);
add(save); setSize(300, 200); setVisible(true);
}
public static void main(String[] args) { SwingUtilities.invokeLater(
new Runnable() {
public void run() { new SimpleFileChooser(); } });
}
}
В примере мы создаем небольшое окно с двумя кнопками. После щелчков на этих кнопках на экране появляются диалоговые окна для открытия и сохранения файлов. Заметьте, что на весь пример у нас всего один экземпляр компонента для выбора файлов JFileChooser, хотя мы и сохраняем файлы, и открываем их. Более того, эти действия можно совершать многократно, поскольку, как уже отмечалось, JFileChooser представляет собой обычный компонент, и вы можете создать его один раз, а затем после соответствующей настройки снова и снова выводить в подходящих диалоговых окнах. При щелчке на первой кнопке на экран выводится диалоговое окно открытия файлов. Посмотрите, как можно задать соответствующий заголовок для диалогового окна методом setDialogTitle(). Перед выводом диалогового окна для выбора файлов на экран мы настраиваем режим выбора. Компонент JFileChooser может работать в одном из трех режимов (режим выбора хранится в свойстве fileSelectionMode), перечисленных в табл. 14.5.

Стандартные диалоговые окна |
423 |
|
Таблица 14.5. Доступные режимы работы JFileChooser |
|
|
|
|
|
Режим работы |
Описание |
|
FILES_ONLY |
Пользователю длявыбора(независимооттого, сохраняетсяфайлили |
|
|
открывается) будут доступны только файлы, но не каталоги. По умол- |
|
|
чанию JFileChooser работает именно в этом режиме и правильно де- |
|
|
лает, поскольку подобный режим необходим чаще остальных. Именно |
|
|
в этом режиме пользователь сохраняет свою работу в файлах |
|
FILES_AND_DIRECTORIES |
В этом режиме пользователь может выбирать и каталоги, и файлы. |
|
|
Как правило, этот режим хорош там, где вы меняете общие свойства |
|
|
файловой системы, и файлы для вас не отличаются от каталогов |
|
DIRECTORIES_ONLY |
Этотвесьмаценныйрежимразрешаетпользователювыбиратьисключи- |
|
|
тельно каталоги. Особенно хорош он там, где нужно выбирать каталоги |
|
|
под временные файлы, указывать каталоги с исходными текстами и т. п. |
Мы выбираем последний режим, так что открыть вы сможете только каталог. Для вывода диалогового окна открытия файлов (в нашем случае каталогов) служит удобный метод showOpenDialog(). Этому методу нужно только передать ссылку на «родительский» компонент, относительно которого окно будет располагаться на экране. В ответ метод возвращает целое число, определяющее сделанный пользователем выбор (табл. 14.6).
Таблица 14.6. Значения, возвращаемые методами класса JFileChooser
Константа |
Описание |
APPROVE_OPTION |
Выбор файла в диалоговом окне прошел успешно, можно получить |
|
выбранный файл методом getFile() |
CANCEL_OPTION |
Пользователь отменил выбор файла, щелкнув на кнопке Cancel |
ERROR_OPTION |
При выборе файла произошла ошибка, или пользователь закрыл диа- |
|
логовое окно для выбора файлов |
В нашем примере мы проверяем, успешен ли был выбор файла, и если да (метод showOpenDialog() вернул нам значение APPROVE_OPTION), выводим на экран имя выбранного каталога (с помощью класса JOptionPane).

424 |
ГЛАВА 14 |
Щелкнув на второй кнопке, вы сможете вызвать на экран диалоговое окно для сохранения файлов. Разница между ним и создаваемым первой кнопкой окном для открытия файлов невелика, всего лишь в надписях, используемых для компонентов JFileChooser. Мы также устанавливаем режим выбора файлов (FILES_ONLY), задаем собственный заголовок для создаваемого окна методом setDialogTitle() и выводим диалоговое окно на экран методом showSaveDialog(). Так же как и в случае окна для открытия файлов, для этого требуется только один параметр — «родительский» компонент. Если выбор файла для сохранения проходит успешно (нам возвращают значение APPROVE_ OPTION), на экране появляется краткое сообщение, подтверждающее успешное сохранение файла (которое, правда, беззастенчиво лукавит, поскольку никакого сохранения не происходит).
Запустив программу с примером, вы сможете выбрать любой файл в своей файловой системе с помощью компонента JFileChooser. Для этого, как нетрудно видеть, нужно всего несколько строк кода. Но не забывайте, что компонент JFileChooser предназначен всего лишь для выбора файла, а проводить с выбранным файлом соответствующие манипуляции (записывать в него информацию или анализировать его содержимое) вам придется своими руками.
Вопрос с переводом англоязычных строк в приложении, использующим компонент JFileChooser, не отличается от подхода в компоненте JOptionPane. По умолчанию все строки написаны на английском языке (что легко видеть на снимке экрана), они берутся они из специальных ресурсов класса UIManager. Например, заменить надпись Open можно так: UIManager.put(«FileChooser.openButtonText», «Открыть»). Заменив эти ресурсы на строки, написанные на нужном вам языке, вы сможете перевести стандартные диалоги (но заменять строки необходимо перед созданием компонентов). Ну а полный список ключей для этих строк размещен в интерактивной документации JDK и Swing.
Фильтры файлов
По умолчанию в списке файлов, который компонент JFileChooser предоставляет пользователю, содержатся все файлы из текущего каталога (того, что пользователь просматривает в данный момент). Порой это очень неудобно: как правило, пользователю необходим файл с определенным именем или типом, и ему приходится «рыскать» по всему списку в поиске нужного (только представьте себе поиск нужного файла среди нескольких тысяч). Мы можем сократить круг поиска пользователя с помощью фильтра файлов, который легко встраивается в компонент JFileChooser.
Фильтры файлов для JFileChooser описаны абстрактным классом FileFilter из пакета javax.swing.filechooser. Дело происходит следующим образом: вы наследуете от класса FileFilter, основным методом которого является accept(). Этот метод класс JFileChooser вызывает для каждого файла, перед тем, как добавить его в список файлов, предоставляемых для выбора пользователю. Вы, в методе accept(), анализируете файл (как правило, по имени, хотя никто не запрещает вам анализировать файл по его содержимому, если вы захотите удостовериться, что оно соответствует определенному формату) и решаете, «достоин» ли файл появления перед глазами пользователя6. Рассмотрим несложный пример, в котором попробуем написать собственный фильтр файлов:
//FilteringFiles.java
//Фильтры файлов в компоненте JFileChooser import javax.swing.*;
import javax.swing.filechooser.*;
6 Это не что иное, как шаблон проектирования стратегия (strategy)., один из самых распространенных в Swing.