Материал: Портянкин И. Swing

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Контейнеры высшего уровня

145

Окно с рамкой JFrame

Окно с рамкой JFrame унаследовано от класса JWindow и представляет собой наиболее часто используемое в приложениях окно «общего назначения». В отличие от окон JWindow окна JFrame обладают рамкой (которая позволяет пользователям легко изменять их размер), заголовком с названием приложения (хотя можно оставлять этот заголовок пустым), иногда системным меню (позволяющим проводить манипуляции с этим окном) и кнопками для управления окном (чаще всего для его закрытия и свертывания). Именно класс JFrame применяется в подавляющем большинстве приложений для размещения компонентов пользовательского интерфейса. Прежде почти всегда при создании окна с рамкой приходилось заботиться о том, чтобы при щелчке пользователем на кнопке закрытия окна приложение заканчивало работу, а необходимость даже для самого скромного приложения писать слушателя событий от окна сильно раздражала. Создатели Swing услышали ропот недовольных программистов и добавили в класс JFrame специальный метод, позволяющий упростить эту операцию. Рассмотрим небольшой пример:

//FrameClosing.java

//Использование окна с рамкой import javax.swing.*;

public class FrameClosing extends JFrame { public FrameClosing() {

super("Заголовок Окна");

//операция при закрытии окна setDefaultCloseOperation(EXIT_ON_CLOSE);

//значок для окна

setIconImage(getToolkit().getImage("icon.gif")); // вывод на экран

setSize(300, 100); setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new FrameClosing(); } });

}

}

Это, наверное, самый простой пример в книге. Мы создаем в нем подкласс JFrame, указываем заголовок окна (в конструкторе базового класса, хотя можно было бы использовать и метод setTitle()) и, прежде чем задать размеры окна и вывести его на экран, вызываем метод setDefaultCloseOperation(). Он позволяет указать, какое действие будет произведено в методе предварительной обработки событий processWindowEvent() при закрытии окна. По умолчанию применяется константа HIDE_ON_CLOSE, убирающая с экрана окно при его закрытии. Мы использовали (и на протяжении книги почти всегда будем использовать) значение EXIT_ON_CLOSE, которое указывает, что при закрытии окна необходимо закончить работу приложения. Остальные варианты вы сможете найти в интерактивной документации. В книге имеется множество примеров размещения компонентов вашего пользовательского интерфейса в окне с рамкой, даже в этой главе

146

ГЛАВА 6

мы уже успели несколько раз его встретить, поэтому мы не станем рассматривать здесь еще один пример. Остается лишь сказать о довольно полезном методе setIconImage(), позволяющем задать значок для вашего окна (в зависимости от платформы он может находиться только на кнопке свернутого окна или в заголовке окна в нормальном состоянии). Собственный значок позволит вашему приложению «выделиться», так что пользователь легче его запомнит.

Из дополнительных возможностей окна с рамкой JFrame можно упомянуть о его способности «прятать» свои «украшения»: рамку и элементы управления окном. Делает это метод setUndecorated(true). После его вызова окно JFrame будет разительно похоже на уже знакомое нам окно без рамки. Пока непонятно, зачем нужно это делать, но вскоре мы найдем применение данному методу (правда, вызывать его нужно до того, как окно появится на экране). Также стоит упомянуть метод setExtendedState(). Он позволяет задать состояние окна, например, свернуть его, но к сожалению работает на разных платформах по-разному, так что совсем полагаться на него не стоит, но всегда можно узнать, какие операции с окном поддерживаются на данной платформе с помощью метода isFrameStateSupported() из класса Toolkit.

События окон

Окна Swing (JWindow, JFrame, а также еще не рассмотренное нами диалоговое окно JDialog) поддерживают три типа событий: первое, представленное слушателем WindowListener, позволяет узнать об изменениях в состоянии окна, второе, со слушателем WindowFocusListener, генерируется системой передачи фокуса ввода и сообщает о получении или потере компонентами окна фокуса ввода, наконец, третье, со слушателем WindowStateListener, сообщает о изменении состояния окна, например сворачивании. Полный список методов данных слушателей вы сможете найти в интерактивной документации Java, в дополнение к этому можно лишь сказать, что от событий окон немного толку. Без сомнения, вы сможете узнать обо всех изменениях в состоянии окна, но при этом у вас почти нет рычагов управления окнами, потому что они полностью принадлежат операционной системе. В результате обычно вы работаете с компонентами Swing,

аокно используете просто как площадку для их размещения.

Винтерфейсе слушателя WindowListener довольно много методов, и они редко требуются все вместе. Чаще остальных применяют метод windowClosing(), вызываемый си-

стемой событий при попытке пользователя закрыть окно, так что вы можете провести какие-то действия перед закрытием окна (например, запомнить все документы и настройки приложения) или спросить пользователя, уверен ли он в том, что хочет закончить работу. Рассмотрим небольшой пример с этим методом:

//ConfirmClosing.java

//Подтверждение о выходе из приложения import javax.swing.*;

import java.awt.event.*;

public class ConfirmClosing extends JFrame { public ConfirmClosing() {

super("Приложение");

//отключаем операцию закрытия setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

//добавляем слушателя событий от окна addWindowListener(new WindowAdapter() {

Контейнеры высшего уровня

147

@Override

public void windowClosing(WindowEvent e) { // потверждение выхода

int res = JOptionPane.

showConfirmDialog(null, "Действительно выйти?"); if ( res == JOptionPane.YES_OPTION )

System.exit(0);

}

}); // выводим окно на экран

setSize(200, 100); setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new ConfirmClosing(); } });

}

}

МысоздаемнебольшоеокноJFrameидобавляемкнемуслушателясобытийWindowEvent. Чтобы не реализовывать все определенные в интерфейсе WindowListener методы, мы наследуем от адаптера WindowAdapter и переопределяем нужный нам метод windowClosing(). При закрытии окна мы спрашиваем у пользователя, действительно ли он желает закончить работу с приложением, и завершаем работу, если ответ положительный. Кстати, обратите внимание, что нам приходится указывать в методе setDefaultCloseOperation(), что при закрытии окна ничего делать не надо (передавая в него константу DO_NOTHING_ON_ CLOSE), иначе окно скроется с глаз пользователя при любой реакции последнего.

Диалоговое окно JDialog

Диалоговые окна довольно часто используются в приложениях для получения информации, не имеющей прямого отношения к основному окну, например, для установки параметров, вывода важной вспомогательной информации, получения дополнительной информации от пользователя. Диалоговые окна могут быть модальными (modal) — они запрещают всем остальным окнам приложения получать информацию от пользователя, пока тот не закончит работу с модальным диалоговым окном. Модальные диалоговые окна полезны в тех ситуациях, когда информация, получаемая от пользователя, коренным образом меняет работу приложения и поэтому до ее получения продолжение работы невозможно. Внешний вид диалоговых окон мало отличается от окон с рамкой JFrame, но обычно у них меньше элементов управления (чаще всего, имеется только кнопка закрытия окна) и отсутствует системное меню. Как правило, диалоговые окна всегда располагаются поверх основного окна приложения, напоминая о том, что необходимо завершить ввод информации.

Диалоговые окна в Swing реализуются классом JDialog. Данный класс позволяет создавать обычные и модальные диалоговые окна, поддерживает (так же как и класс JFrame) закрытие окна, а в остальном сходен с другими окнами Swing, потому что унаследован от базового класса окон JWindow. При создании диалоговых окон Swing необходимо указы-

148

ГЛАВА 6

вать «родительское окно», которым может быть окно с рамкой JFrame или любое другое окно, унаследованное от базового класса окон Window (для удобства есть конструктор, не требующий «родительского» окна, но использующий вспомогательное невидимое окно, о котором мы говорили в разделе об окнах без рамки JWindow). Как уже отмечалось, диалоговое окно располагается на экране с учетом положения «родительского» окна. Рассмотрим небольшой пример, где создадим пару диалоговых окон:

//DialogWindows.java

//Диалоговые окна в Swing import javax.swing.*; import java.awt.event.*; import java.awt.*;

public class DialogWindows extends JFrame { public DialogWindows() {

super("DialogWindows");

//выход при закрытии setDefaultCloseOperation(EXIT_ON_CLOSE);

//пара кнопок, вызывающих создание диалоговых окон

JButton button1 = new JButton("Обычное окно"); button1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

JDialog dialog = createDialog("Немодальное",

Dialog.ModalityType.MODELESS);

dialog.setVisible(true);

}

});

JButton button2 = new JButton("Модальное окно"); button2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) {

JDialog dialog = createDialog("Модальное",

Dialog.ModalityType.APPLICATION_MODAL); dialog.setVisible(true);

}

});

//создаем панель содержимого и выводим окно на экран

JPanel contents = new JPanel(); contents.add(button1); contents.add(button2); setContentPane(contents); setSize(350, 100);

Контейнеры высшего уровня

149

setVisible(true);

}

// создает диалоговое окно

private JDialog createDialog(String title, Dialog.ModalityType modal){

JDialog dialog = new JDialog(this, title, modal); dialog.setDefaultCloseOperation(DISPOSE_ON_CLOSE); dialog.setSize(200, 60);

return dialog;

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new DialogWindows(); } });

}

}

В этом примере мы создаем окно с рамкой JFrame, в панель содержимого которого добавляем две кнопки JButton, щелчками на которых и будут создаваться диалоговые окна. Чтобы не дублировать в слушателях похожий код, мы создали отдельный метод createDialog(), создающий простое диалоговое окно с заданным заголовком и при необходимости модальностью. Заголовок диалогового окна, его «родитель» и признак модальности указываются в конструкторе6. При закрытии диалогового окна мы использовали операцию DISPOSE_ON_CLOSE, удаляющую окно после закрытия. Первая кнопка позволяет создать немодальное диалоговое окно, а вторая — его модальный вариант. Запустив приложение, вы увидите разницу: немодальные окна не запрещают работу с основным окном приложения, и вы можете снова и снова создавать их, не закрывая уже созданные окна. Такое поведение удобно там, где информация, находящаяся в диалоговом окне, не критична, или часто меняется, и каждый раз отвлекаться на модальное окно неудобно (хорошим примером может быть диалоговое окно смены шрифта в текстовом редакторе). Модальные окна запрещают вам работу со всеми остальными окнами приложения. Мы уже отмечали, что такое поведение требуется для получения важной информации, без которой невозможно продолжение работы, например, для получения пароля, позволяющего авторизовать пользователя, или запроса на выход из приложения.

Признак модальности задается с помощью перечисления (enum) из класса AWT Dialog, значения которого могут быть следующими:

Таблица 6.3. Виды модальности диалогов Swing

Вид модальности

Описание

 

 

MODELESS

Диалоговое окно не препятствует работе остальных окон, в том

 

числе и родительского, но всегда находится выше родительского

 

окна

6 Нетрудно задать эти качества вашего диалогового окна и с помощью свойств title и modalityType. Смысл здесь в том, что при создании (вызове конструктора) диалогового окна вы чаще всего уже прекрасно знаете, каким оно должно быть.

Источник: https://studfile.net/preview/15935977/