Слайд 1Программирование на Java
Тема 6.3 Программирование GUI с использованием Swing
Слайд 2 Обработка событий в Swing
Паттерн проектирования «наблюдатель»:
Паттерны проектирования —
это стандартные приемы объектно-ориентированного программирования, позволяющие оптимальным образом справиться с
нетривиальными, но часто возникающими в программировании ситуации. Паттерн проектирования описывает классы, которые необходимо ввести для разрешения такой ситуации и взаимодействие между классами.
Паттерн проектирования «наблюдатель» применяется, когда один объект должен оповещать другие о произошедших с ним изменениях или внешних воздействиях. Такой объект называется наблюдаемым, а объекты, которые следует оповестить — наблюдателями.
Для того, чтобы подобное взаимодействие было возможным, объект-наблюдатель должен иметь метод (или несколько методов) с заранее определенной сигнатурой (именем и параметрами). Когда с наблюдаемым объектом произойдет ожидаемое событие, он вызовет соответствующий метод у своего наблюдателя. В этом методе и будет запрограммирована реакция на событие.
Слайд 3 Обработка событий в Swing
Графический интерфейс пользователя включает в
себя не только расположение в окне необходимых элементов управления, но
и назначение реакции на пользовательские события. Большая честь действий в оконных программах выполняется в ответ на выбор пользователем команд меню, нажатие кнопок, а иногда даже просто в ответ на ввод нового символа в текстовое поле.
Таким образом, при разработке программы необходимо:
Выявить события, в ответ на которые потребуется реакция программы.
Написать код, реализующий эту реакцию (так называемый обработчик событий).
Связать обработчик события с соответствующим событием.
Первый пункт зависит от логики работы приложения и находится всецело на усмотрении программиста. Обработчик события — это, как правило, обычный метод и ничего особенного в его написании нет.
В разных языках программирования и визуальных библиотеках используются самые различные способы привязки процедуры (метода), которая должна вызываться в ответ на некоторое событие, к самому этому событию. В частности, в Turbo C++ Explorer (C++ Builder) процедура просто должна иметь особое название, состоящее из имени компонента и типа обрабатываемого события.
В библиотеке Swing для привязки обработчика события к вызывающему его компоненту используется паттерн проектирования «наблюдатель» (см. слайд).
Для того, чтобы наблюдаемый объект мог вызвать метод наблюдателя, он должен знать о том, что такой наблюдатель существует. Поэтому у наблюдаемого предварительно должен быть вызван специальный метод, регистрирующий его наблюдателя.
Заметим, что в данной схеме один наблюдатель может быть зарегистрирован у нескольких объектов (т.е. одинаково реагировать на изменения в каждом из них), а у одного объекта может быть несколько наблюдателей (т.е. при возникновении события выполняется несколько независимых методов-обработчиков). Это весьма увеличивает гибкость программирования.
Слайд 4 Обработка событий в Swing
Механизм обработки событий библиотеки Swing:
В
контексте графического интерфейса пользователя наблюдаемыми объектами являются элементы управления: кнопки,
флажки, меню и т.д. Они могут сообщить своим наблюдателям об определенных событиях(наведение мышкой, нажатие клавиши на клавиатуре, изменение текста в текстовом поле, выбор нового элемента в выпадающем списке и т.д.).
Наблюдателями должны являться объекты классов, поддерживающих специальные интерфейсы (вспомним, что в классе наблюдателя должны быть определенные методы, о которых «знает» наблюдаемый и вызывает их при наступлении события). Такие классы в терминологии Swing называются слушателями.
Слайд 5 Обработка событий в Swing
Интерфейс MouseListener и обработка событий
от мыши:
Методы интерфейса MouseListener:
public void mouseClicked(MouseEvent event) //выполнен
// щелчок мышкой на наблюдаемом объекте
public void mouseEntered(MouseEvent event) //курсор
// мыши вошел в область наблюдаемого объекта
public void mouseExited(MouseEvent event) // курсор
// мыши вышел из области наблюдаемого объекта
public void mousePressed(MouseEvent event) // кнопка
// мыши нажата в момент, когда курсор
// находится над наблюдаемым объектом
public void mouseReleased(MouseEvent event) // кнопка
// мыши отпущена в момент, когда курсор
// находится над наблюдаемым объектом
Слайд 6 Обработка событий в Swing
Мы рассмотрим технологию написания слушателей
на примере слушателей событий мыши.
События от мыши — один из
самых популярных типов событий. Практически любой элемент управления способен сообщить о том, что на него навели мышь, щелкнули по нему и т.д. Об этом будут оповещен все зарегистрированные слушатели событий от мыши.
Слушатель событий от мыши должен реализовать интерфейс MouseListener. В этом интерфейсе перечислены следующие методы (см. слайд).
Каждый из этих методов получает параметр типа MouseEvent, через который передается дополнительная информация о возникшем событии. Например, можно получить объект, вызвавший данное событие, командой event.getSource() (не забывайте, что один и тот же слушатель может быть зарегистрирован в нескольких объектах и иногда ему может понадобиться узнать, какой именно из них вызвал данный метод). Метод getPoint() вернет координаты точки, в которой находился курсор мыши, когда было инициировано событие. Метод getClickCount() возвращает число сделанных подряд щелчков (имеет смысл только для mouseClicked() и позволяет особым образом обработать двойной, тройной и т.п. щелчок).
Слайд 7 Обработка событий в Swing
Пример. Окно входа в систему
import
javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
class LoginWindow extends JFrame
{
/* Для того,
чтобы впоследствии обращаться к
* содержимому текстовых полей, рекомендуется
* сделать их членами класса окна */
JTextField loginField;
JPasswordField passwordField;
LoginWindow()
{ super("Вход в систему");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Слайд 8 Обработка событий в Swing
// Настраиваем первую горизонтальную панель
(для ввода логина)
Box box1 = Box.createHorizontalBox();
JLabel loginLabel = new JLabel("Логин:");
loginField
= new JTextField(15);
box1.add(loginLabel);
box1.add(Box.createHorizontalStrut(6));
box1.add(loginField);
// Настраиваем вторую горизонтальную панель (для ввода пароля)
Box box2 = Box.createHorizontalBox();
JLabel passwordLabel = new JLabel("Пароль:");
passwordField = new JPasswordField(15);
box2.add(passwordLabel);
box2.add(Box.createHorizontalStrut(6));
box2.add(passwordField);
Слайд 9 Обработка событий в Swing
// Настраиваем третью горизонтальную панель
(с кнопками)
Box box3 = Box.createHorizontalBox();
JButton ok = new JButton("OK");
JButton cancel
= new JButton("Отмена");
box3.add(Box.createHorizontalGlue());
box3.add(ok);
box3.add(Box.createHorizontalStrut(12));
box3.add(cancel);
// Уточняем размеры компонентов
loginLabel.setPreferredSize(passwordLabel.getPreferredSize());
// Размещаем три горизонтальные панели на одной вертикальной
Box mainBox = Box.createVerticalBox();
mainBox.setBorder(new EmptyBorder(12,12,12,12));
mainBox.add(box1);
mainBox.add(Box.createVerticalStrut(12));
mainBox.add(box2);
Слайд 10 Обработка событий в Swing
mainBox.add(Box.createVerticalStrut(17));
mainBox.add(box3);
setContentPane(mainBox);
pack();
setResizable(false);
}
}
public class Program
{
public static void main (String [] args)
{
JFrame myWindow = new LoginWindow();
myWindow.setVisible(true);
}
}
Слайд 11 Обработка событий в Swing
В качестве примера рассмотрим окно
для входа в систему. Это окно содержит два текстовых поля
для ввода логина и пароля, подписи к этим полям и кнопки «OK» и «Отмена».
В первую очередь необходимо сделать на бумаге эскиз будущего окна, чтобы определиться, где должны быть расположены элементы управления и какой менеджер расположения должен быть выбран.
В нашем окне нет элементов, которые имеет смысл растягивать на все доступное пространство, поэтому будем использовать один из менеджеров, сохраняющих предпочтительные размеры компонентов, а именно — BoxLayout. Проще всего представить наше окно как три горизонтальные панели, объединенные в одной вертикальной. В первой из них будет надпись «Логин:» и текстовое поле. Во второй — надпись «Пароль:» и поле для ввода пароля. В третьей будут размещены две кнопки. При этом необходимо учесть следующее:
Кнопки «ОК» и «Отмена» принято прижимать к правому краю окна, поэтому в начале третьей горизонтальной панели необходимо добавить «пружину».
Должно выдерживаться аккуратное расстояние между элементами. В частности, для стиля Java разработаны следующие рекомендации. Тесно связанные элементы (такие как текстовое поле и подпись к нему) должны отстоять друг от друга на 6 пикселов. Логически сгруппированные элементы — на 12 пикселов (в нашем случае это две верхние панели и пара кнопок). Все остальные элементы должны находиться на расстоянии 17 пикселов друг от друга. Не следует забывать и про рамку окна.
Элементы должны быть аккуратно выровнены. В нашем случае надписи, которые мы собираемся поместить перед текстовыми полями, наверняка будут разной длины и из-за этого поля будут сдвинуты относительно друг друга, что не желательно. Поэтому следует принудительно задать у надписей одинаковую ширину.
При увеличении размеров окна текстовые поля будут не эстетично изменять свою высоту. Можно ее зафиксировать, а можно просто запретить окну изменять свои размеры после упаковки командой setResizable(false).
Итоговый код окна приведен на слайдах.
Слайд 12 Обработка событий в Swing
Пример. Класс слушателя
class MouseL implements
MouseListener
{ public void mouseClicked(MouseEvent event)
{ if
(loginField.getText().equals("Иван"))
JOptionPane.showMessageDialog(null, "Вход выполнен");
else JOptionPane.showMessageDialog(null, "Вход НЕ выполнен");
}
public void mouseEntered(MouseEvent event){}
public void mouseExited(MouseEvent event){}
public void mousePressed(MouseEvent event){}
public void mouseReleased(MouseEvent event){}
}
Пример. Создание объекта слушателя и прикре-
пление его к кнопке “OK”
JButton ok = new JButton("OK");
ok.addMouseListener(new MouseL());
Слайд 13 Обработка событий в Swing
Чтобы обработать нажатие на кнопку,
требуется описать класс, реализующий интерфейс MouseListener, причем метод mouseClicked() должен содержать обработчик
события. Далее необходимо создать объект этого класса и зарегистрировать его как слушателя интересующей нас кнопки. Для регистрации слушателя используется метод addMouseListener(MouseListener listener).
Опишем класс слушателя в пределах класса окна LoginWindow, после конструктора. Обработчик события будет проверять, ввел ли пользователь логин «Иван» (пароль проверять не будем) и выводить сообщение об успехе или неуспехе входа в систему (работа стандартных диалоговых окон обсуждается дальше .
Мы сделали слушателя вложенным классом класса LoginWindow, чтобы он мог легко получить доступ к его внутренним полям loginField и passwordField. Кроме того, хотя реально мы обрабатываем только одно из пяти возможных событий мыши, описывать пришлось все пять методов (четыре имеют пустую реализацию). Дело в том, что в противном случае класс пришлось бы объявить абстрактным (ведь он унаследовал от интерфейса пустые заголовки методов) и мы не смогли бы создать объект этого класса. А мы должны создать объект слушателя и прикрепить его к кнопке. Для этого в код конструктора LoginWindow() необходимо добавить команду :
ok.addMouseListener(new MouseL());
Это можно сделать сразу после команды:
JButton ok = new JButton("OK");
Слайд 14 Обработка событий в Swing
Пример. Создание слушателей с помощью
анонимных классов (Замена вложенного класса слушателя на анонимный):
Удаляем описание
класса MouseL
Команду ok.addMouseListener(new MouseL()); заменить на:
ok.addMouseListener(new MouseListener()
{ public void mouseClicked(MouseEvent event)
{ if (loginField.getText().equals("Иван"))
JOptionPane.showMessageDialog(null, "Вход выполнен");
else JOptionPane.showMessageDialog(null, "Вход НЕ выполнен");
}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mousePressed(MouseEvent event) {}
public void mouseReleased(MouseEvent event) {}
});
Слайд 15 Обработка событий в Swing
Чтобы кнопка ok обрела слушателя, который будет
обрабатывать нажатие на нее, нам понадобилось описать новый (вложенный) класс.
Иногда вместо вложенного класса можно обойтись анонимным.
Как вы помните, анонимный класс не имеет имени и в программе может быть создан только один объект этого класса (создание которого совмещено с определением класса). Но очень часто, как и в нашем примере, слушатель пишется для того, чтобы обрабатывать события единственного объекта — в нашем случае кнопки ok, а значит, используется в программе только однажды: во время привязки к этому объекту. Таким образом, мы можем заменить вложенный класс анонимным (см. слайд).
Новый вариант выглядит более громоздко, чем первый. Злоупотребление анонимными классами может сделать программу плохо читаемой. Однако в результате все действия с кнопкой (создание, настройка ее внешнего вида и команды обработки щелчка по ней) не разнесены, как в случае вложенных классов, а находятся рядом, что облегчает сопровождение (внесение изменений) программы. В случае простых (в несколько строк) обработчиков разумно делать выбор в пользу анонимных классов.
Вообще, можно реализовать интерфейс слушателя в любом классе, добавив к его описанию директиву implements MouseListener и определив в нем необходимые методы. В частности, это может быть сам класс окна SimpleWindow. Но чаще всего пользуются анонимными и вложенными классами .
Слайд 16 Обработка событий в Swing
Пример. Класс MouseAdapter
ok.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent event)
{ if (loginField.getText().equals("Иван"))
JOptionPane.showMessageDialog(null, "Вход выполнен");
else JOptionPane.showMessageDialog(null, "Вход НЕ выполнен");
}
});
Слайд 17 Обработка событий в Swing
Программа стала выглядеть загроможденной главным
образом из-за того, что помимо полезного для нас метода mouseClicked() нам
пришлось определять пустые реализации всех остальных, не нужных методов. В принципе, этого можно избежать.
Класс MouseAdapter реализует интерфейс MouseListener, определяя пустые реализации для каждого из его методов. Можно унаследовать своего слушателя от этого класса и переопределить те методы, которые нам нужны.
В результате предыдущее описание слушателя будет выглядеть более компактно: (см. слайд).
Слайд 18 Обработка событий в Swing
Общая структура слушателей:
Каждый слушатель
должен реализовывать интерфейс ***Listener, где *** — тип слушателя.
Каждому из интерфейсов (за
исключением тех, в которых всего один метод) соответствует пустой класс-заглушка ***Adapter
Каждый метод интерфейса слушателя принимает один параметр типа ***Event
Метод add***Listener(***Listener listener) привязывает слушателя к объекту
Пример: Слушатель MouseListener
Интерфейс MouseListener
Класс-заглушка MouseAdapter
Каждый метод интерфейса MouseListener принимает один параметр типа MouseEvent
Регистрируется слушатель методом addMouseListener(MouseListener listener).
Слайд 19 Обработка событий в Swing
Кроме слушателей MouseListener визуальные компоненты Swing поддерживают
целый ряд других слушателей (заметим, что в разных компонентах набор
возможных слушателей может отличаться).
Каждый слушатель должен реализовывать интерфейс ***Listener, где *** — тип слушателя.
Практически каждому из этих интерфейсов (за исключением тех, в которых всего один метод) соответствует пустой класс-заглушка ***Adapter.
Каждый метод интерфейса слушателя принимает один параметр типа ***Event, в котором собрана вся информация, относящаяся к событию.
Чтобы привязать слушателя к объекту (который поддерживает соответствующий тип слушателей) используется метод add***Listener(***Listener listener).
Например, слушатель MouseListener должен реализовать интерфейс с таким же именем, которому соответствует класс-заглушка MouseAdapter. Методы этого интерфейса обрабатывают параметр типа MouseEvent, а регистрируется слушатель методом addMouseListener(MouseListener listener). Мы не будем повторять эту информацию для других типов слушателей, они работают аналогично.
Слайд 20 Обработка событий в Swing
Слушатель фокуса FocusListener
Методы интерфейса FocusListener :
public
void focusGained(FocusEvent event) // вызывается,
// когда наблюдаемый объект получает фокус
public void focusLost(FocusEvent event) // вызывается, когда
// наблюдаемый объект теряет фокус
Слушатель колесика мышки MouseWheelListener
Метод интерфейса MouseWheelListener :
public void mouseWheelMoved(MouseWheelEvent event)
Слушатель клавиатуры KeyListener
Методы интерфейса KeyListener :
public void mouseKeyTyped(KeyEvent event) //вызывается, когда
// с клавиатуры вводится символ
public void mouseKeyPressed(KeyEvent event) // вызывается,
// когда нажата клавиша клавиатуры
public void mouseKeyReleased(KeyEvent event) // вызывается,
// когда отпущена клавиша клавиатуры
Слайд 21 Обработка событий в Swing
Слушатель FocusListener отслеживает моменты, когда объект получает
фокус (то есть становится активным) или теряет его. Концепция фокуса
очень важна для оконных приложений. В каждый момент времени в окне может быть только один активный (находящийся в фокусе) объект, который получает информацию о нажатых на клавиатуре клавишах (т.е. реагирует на события клавиатуры), о прокрутке колесика мышки и т.д. Пользователь активирует один из элементов управления нажатием мышки или с помощью клавиши Tab (переключаясь между ними). Методы интерфейса FocusListener представлены на слайде.
Слушатель MouseWheelListener оповещается при вращении колесика мыши в тот момент, когда данный компонент находится в фокусе. Этот интерфейс содержит всего один метод: (см. на слайде).
Слушатель KeyListener оповещается, когда пользователь работает с клавиатурой в тот момент, когда данный компонент находится в фокусе. В интерфейсе определены методы: (см. слайд). Аргумент event этих методов способен дать весьма ценные сведения.
В частности, команда event.getKeyChar()возвращает символ типа char, связанный с нажатой клавишей. Если с нажатой клавишей не связан никакой символ, возвращается константа CHAR_UNDEFINED.
Команда event.getKeyCode() возвратит код нажатой клавиши в виде целого числа типа int. Его можно сравнить с одной из многочисленных констант, определенных в классе KeyEvent: VK_F1,VK_SHIFT, VK_D, VK_MINUS и т.д.
Методы isAltDown(), isControlDown(), isShiftDown() позволяют узнать, не была ли одновременно нажата одна из клавиш-модификаторов Alt, Ctrl или Shift.
Слайд 22 Обработка событий в Swing
Слушатель изменения состояния ChangeListener
Метод интерфейса
ChangeListener :
public void stateChanged(ChangeEvent event)
Слушатель событий окна WindowListener
Методы интерфейса
WindowListener :
public void windowOpened(WindowEvent event) //окно открылось
public void windowClosing(WindowEvent event)//попытка закрытия
//окна
public void windowClosed(WindowEvent event) //окно закрылось
public void windowIconified(WindowEvent event) //окно свернуто
public void windowDeiconified(WindowEvent event)окно развернуто
public void windowActivated(WindowEvent event) //окно стало
//активным
public void windowDeactivated(WindowEvent event) //окно стало
//неактивным
Слайд 23 Обработка событий в Swing
Слушатель ChangeListener реагирует на изменение состояния объекта.
Каждый элемент управления по своему определяет понятие «изменение состояния». Например,
для панели со вкладками JTabbedPane это переход на другую вкладку, для ползунка JSlider — изменение его положения, кнопка JButton рассматривает как смену состояния щелчок на ней. Таким образом, хотя событие это достаточно общее, необходимо уточнять его специфику для каждого конкретного компонента. В интерфейсе определен всего один метод (см. слайд).
Слушатель WindowListener может быть привязан только к окну и оповещается о различных событиях, произошедших с окном: (см. слайд).
Слайд 24 Обработка событий в Swing
Слушатель событий компонента СomponentListener
Методы интерфейса
СomponentListener :
public void componentMoved(ComponentEvent event) /* вызывается, когда наблюдаемый компонент перемещается
(в результате вызова команды setLocation(), работы менеджера размещения или еще по какой-то причине)*/
public void componentResized(ComponentEvent event)//вызывается,
// когда изменяются размеры наблюдаемого компонента
public void componentHidden(ComponentEvent event) //вызывается,
// когда компонент становится невидимым
public void componentShown(ComponentEvent event) // вызывается,
// когда компонент становится видимым
Слушатель выбора элемента ItemListener
Метод интерфейса:
public void itemStateChanged(ItemEvent event)
Слайд 25 Обработка событий в Swing
Слушатель ComponentListener оповещается, когда наблюдаемый визуальный компонент
изменяет свое положение, размеры или видимость. В интерфейсе четыре метода:
(см. слайд).
Слушатель ItemListener реагирует на изменение состояния одного из элементов, входящих в состав наблюдаемого компонента. Например, выпадающий список JComboBox состоит из множества элементов и слушатель реагирует, когда изменяется выбранный элемент. Также данный слушатель оповещается при выборе либо отмене выбора флажкаJCheckBox или переключателя JRadioButton, изменении состояния кнопки JToggleButton и т.д. Слушатель обладает одним методом: (см. слайд).
Слайд 26 Обработка событий в Swing
Универсальный слушатель ActionListener
Метод интерфейса ActionListener
:
public void actionPerformed(ActionEvent event)
Пример. Обработка нажатия на кнопку ok :
ok.addMouseListener(new ActionListener()
{ public void actionPerformed(ActionEvent event)
{ if (loginField.getText().equals("Иван"))
JOptionPane.showMessageDialog(null, "Вход выполнен");
else JOptionPane.showMessageDialog(null, "Вход НЕ выполнен");
}
});
Слайд 27 Обработка событий в Swing
Среди многочисленных событий, на которые
реагирует каждый элемент управления (и о которых он оповещает соответствующих
слушателей, если они к нему присоединены), есть одно основное, вытекающее из самой сути компонента и обрабатываемое значительно чаще, чем другие. Например, для кнопки это щелчок на ней, а для выпадающего списка — выбор нового элемента.
Для отслеживания и обработки такого события может быть использован особый слушатель ActionListener, имеющий один метод: (см. слайд).
У использования ActionListener есть небольшое преимущество в эффективности (так, при обработке нажатия на кнопку не надо реагировать на четыре лишних события — ведь даже если методы-обработчики пустые, на вызов этих методов все равно тратятся ресурсы). А кроме того очень удобно запомнить и постоянно использовать один класс с одним методам и обращаться к остальным лишь в тех относительно редких случаях, когда возникнет такая необходимость.
Слайд 28 Работа с меню в Swing
Создание главного меню (класс
JMenuBar)
Пример. Главное меню окна, состоящее из двух подменю: «Файл»
и «Правка» с выпадающим подменю :
import javax.swing.*;
import java.awt.event.*;
class SimpleWindow extends JFrame
{ SimpleWindow()
{ super("Окно с меню");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("Файл");
fileMenu.add(new JMenuItem("Новый"));
fileMenu.add(new JMenuItem("Открыть",new ImageIcon("newy.png")));
fileMenu.add(new JMenuItem("Сохранить"));
fileMenu.addSeparator();
fileMenu.add(new JMenuItem("Выйти"));
Слайд 29 Работа с меню в Swing
JMenu editMenu = new
JMenu("Правка");
editMenu.add(new JMenuItem("Копировать"));
JMenu pasteMenu = new JMenu("Вставить");
pasteMenu.add(new JMenuItem("Из буфера"));
pasteMenu.add(new JMenuItem("Из файла"));
editMenu.add(pasteMenu);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(Box.createHorizontalGlue());
menuBar.add(new JLabel(new ImageIcon("newy.png")));
setJMenuBar(menuBar);
setSize(250,150);
}
}
public class Program
{ public static void main (String [] args)
{ JFrame myWindow = new SimpleWindow();
myWindow.setVisible(true);
}
}
Слайд 30 Работа с меню в Swing
Главное меню окна представлено
в Swing классом JMenuBar. По сути своей этот класс представляет собой
панель с менеджером расположения BoxLayout (по горизонтали), в которую можно добавлять не только элементы меню, но и что угодно: хоть выпадающие списки, хоть панели с закладками. Однако для удобства пользования программой предпочтительнее использовать «традиционные» возможности меню.
Элементами главного меню являются обычные меню — выпадающие прямоугольные блоки команд — объекты класса JMenu. Конструктор JMenu(String title) принимает один параметр: название меню, которое будет отображаться в строке главного меню.
Меню, в свою очередь, состоит из пунктов меню, представленных классом JMenuItem. По логике работы пункты меню аналогичны кнопке JButton, то есть, при нажатии на него пользователем выполняется какое-то действие.
У класса JMenuItem есть наследники. Класс JCheckBoxMenuItem по логике работы аналогичен флажку JCheckBox — то есть, прямо в меню можно установить или сбросить какой-либо параметр логического типа. Класс JRadioButtonMenuItem эмулирует переключатель, позволяя выбрать только одну из нескольких альтернатив.
Создать элемент меню можно пустым конструктором JMenuItem , либо (что более востребовано) одним из конструкторов, в которые передается текст и/или значок элемента меню: JMenuItem(String text), JMenuItem(Icon icon),JMenuItem(String text, Icon icon). Конечно, в любой момент текст и значок можно сменить методами setText(String text) и setIcon(Icon icon) соответственно.
Элемент добавляется в меню методом add(JMenuItem item) класса JMenu. Чтобы отделить группы взаимосвязанных элементов меню, можно добавить между ними разделитель методом addSeparator() класса JMenu.
Кроме того, в меню можно добавить и другое меню. В этом случае образуется последовательность вложенных друг в друга подменю, что довольно часто встречается в современных программах. Но не следует увлекаться: глубина вложенности более трех уровней скорее всего приведет к неудобствам пользования программой.
Главное меню должно быть присоединено к окну методом setJMenuBar(JMenuBar menuBar).
Слайд 31 Работа с меню в Swing
Создание главного меню (класс
JMenuBar)
Пример. Главное меню окна, состоящее из двух подменю: «Файл»
и «Правка» с выпадающим подменю . Обработка команд меню:
// заменить в предыдущем примере оператор:
fileMenu.add(new JMenuItem("Выйти"));
// на операторы:
JMenuItem exit = new JMenuItem("Выйти");
exit.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent event)
{System.exit(0);}
});
fileMenu.add(exit);
Слайд 32 Работа с меню в Swing
Как было сказано, каждый
элемент меню по сути представляет собой кнопку, поэтому реагирует на
те же события и позволяет присоединять к себе тех же слушателей, что и кнопка. Поэтому мы можем назначить реакцию на команды меню точно также, как делали это выше (см. слайд).
Слайд 33 Работа с меню в Swing
Создание контекстного меню (класс
JPopupMenu)
Пример. К уже созданному окну добавляется метка с надписью
и контекстное меню из двух элементов, связанное с этой меткой :
// в определении класса окна следует ввести два поля:
JPopupMenu popup; JLabel label;
// добавить в конструктор перед последней командой (setSize)
label = new JLabel("ЕЛКА", new ImageIcon("newy.png"), JLabel.RIGHT);
JPanel panel = new JPanel();
panel.add(label);
popup = new JPopupMenu();
popup.add(new JMenuItem("Зажечь"));
popup.add(new JMenuItem("Сжечь"));
label.addMouseListener(new MouseAdapter()
{ public void mouseClicked(MouseEvent event)
{if (SwingUtilities.isRightMouseButton(event))
popup.show(label, event.getX(), event.getY());
}
});
setContentPane(panel);
Слайд 34 Работа с меню в Swing
Контекстное (или всплывающее) меню
реализовано в классе JPopupMenu, очень похожему на класс JMenu. Отличительным методом этого
класса является метод show(Component comp, int x, int y), отображающий меню в точке с заданными координатами относительно границ заданного компонента.
Как уже отмечалось, контекстное меню, как правило, отображается при щелчке правой кнопкой мыши над компонентом. Таким образом, чтобы отобразить меню, требуется добавить к этому компоненту слушателя мыши.
Рассмотрим пример, в котором к уже созданному нами окну добавляется метка с надписью и контекстное меню из двух элементов, связанное с этой меткой. Необходимо добавить в конструктор перед последней командой (setSize) следующий код: (см. слайд).
При этом в определении класса окна следует ввести два поля:
JPopupMenu popup; JLabel label;
Это необходимо для того, чтобы анонимный класс-слушатель мог обратиться к метке и к контекстному меню.
Приведенный пример также иллюстрирует применение полезного метода isRightMouseButton(MouseEvent event), определенного в классе вспомогательных утилит SwingUtilities. Метод получает информацию о событии мыши и отвечает на вопрос, была ли нажата именно правая кнопка мыши. Методы getX() и getY() возвращают координаты курсора мыши относительно наблюдаемого компонента.
Слайд 35 Работа с меню в Swing
Стандартные диалоговые окна
Класс JOptionPane
Пример. Предупреждающий диалог:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class SimpleWindow extends JFrame
{ private
JButton button;
SimpleWindow()
{ super("Предупреждающий диалог");
setDefaultCloseOperation(EXIT_ON_CLOSE);
button = new JButton("Информация");
button.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent event)
{ JOptionPane.showMessageDialog(button, "Не надо было нажимать на эту кнопку", "Информация", JOptionPane.WARNING_MESSAGE);
}
});
Слайд 36 Работа с меню в Swing
getContentPane().setLayout(new FlowLayout());
getContentPane().add(button);
setSize(200,150);
}
}
public class
Program
{ public static void main (String [] args)
{ JFrame myWindow = new SimpleWindow();
myWindow.setVisible(true);
}
}
Слайд 37 Работа с меню в Swing
Неотъемлемой частью большинства программ
являются небольшие диалоговые окна: для вывода пользователю сообщения (например, сообщения
об ошибке), для вопроса, ответ на который важен для выполнения текущего действия (например, просьба подтвердить или отменить запрашиваемую операцию). Эти диалоги могут быть запрограммированы вручную на основе класса JFrame. Однако ввиду того, что они являются типичными для многих программ, Swing предоставляет в распоряжение программиста несколько готовых классов для работы с ними.
Чаще всего используется класс JOptionPane, содержащий несколько статических методов, отображающих стандартные диалоги.
Метод showMessageDialog() выводит на экран диалоговое окно, информирующее пользователя. Оно содержит надпись, значок и кнопку ОК. Существует несколько разновидностей этого метода с разными наборами параметров. Самый простой из них showMessageDialog(Component component, Object content) требует указания компонента, над которым должно появиться диалоговое окно и содержимого окна. Чаще всего содержимым окна является некоторая строка, а вместо первого параметра передается null — тогда окно появляется по центру экрана. Более «продвинутый» вариант showMessageDialog(Component component, Object content, String title, int type) позволяет задать также свой заголовок окна и выбрать его тип (влияет на иконку в окне): сообщение об ошибке (ERROR_MESSAGE), предупреждение (WARNING_MESSAGE), информация (INFORMATION_MESSAGE).
Диалоговое окно является модальным. Это значит, что пока пользователь не нажмет в этом окне кнопку OK, программа окажется заблокирована — пользователь не сможет работать с другими окнами.
Пронаблюдаем действие метода на простом примере: (см. слайд).
Кнопка button сделана полем класса окна, чтобы можно было получить к ней доступ из анонимного класса-слушателя.
Слайд 38 Работа с меню в Swing
Стандартные диалоговые окна
Класс JOptionPane
Пример. Окно вопроса:
class SimpleWindow extends JFrame
{ JButton button;
SimpleWindow()
{
super("Предупреждающий диалог");
setDefaultCloseOperation(EXIT_ON_CLOSE);
button = new JButton("Выход");
button.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent event)
{ if (JOptionPane.showConfirmDialog(button, "Вы уверены, что хотите выйти?") == JOptionPane.YES_OPTION) System.exit(0);
}
});
getContentPane().setLayout(new FlowLayout());
getContentPane().add(button);
setSize(200,150);
}
}
Слайд 39 Работа с меню в Swing
Другое часто используемое диалоговое
окно — окно вопроса. В этом окне несколько кнопок, одну
из которых пользователь должен нажать. В программу, вызывающую это диалоговое окно, возвращается информация о выборе пользователя, на основе которой и строится дальнейший ход работы программы.
Данное окно отображается методом showConfirmDialog(Component component, Object content). Параметры этого метода идентичны по смыслу параметрам showMessageDialog(), но в диалоговом окне появится не одна кнопка, а три: «Yes», «No» и «Cancel». Более того, метод возвращает значение, которое можно сравнить с константами YES_OPTION, NO_OPTION и CANCEL_OPTION. Логику работы с этим методом проиллюстрирует пример: (см. слайд).
Метод имеет еще четыре разновидности с разным набором параметров, позволяющих изменять заголовок и значок окна, а также набор кнопок.
Слайд 40 Работа с меню в Swing
Класс JFileChooser
Swing содержит
готовое окно для выбора файла (полезное, например, для программирования пункта
меню Файл --> Открыть). Объект класса JFileChooser создается простым конструктором без параметров, после чего может выводиться на экран методом showOpenDialog(). Этот метод возвращает результат действий пользователя по выбору файла, который сравнивается с одной из следующих констант:
APPROVE_OPTION — выбор файла прошел успешно. Теперь можно методом getFile() получить выбранный файл.
CANCEL_OPTION — пользователь отменил выбор файла, щелкнув на кнопке Cancel.
ERROR_OPTION — при выборе файла произошла ошибка, либо пользователь закрыл диалоговое окно крестиком.
Метод showSaveDialog() отображает то же самое окно, но теперь оно работает в режиме сохранения. Пользователь выбирает директорию для сохранения файла и может ввести его имя. Метод возвращает результат того же типа, что иshowOpenDialog(). Если выбор пути для сохранения прошел успешно, вызов метода getFile() вернут путь, куда пользователь желает сохранить файл.
Следует иметь в виду, что сам класс JFileChooser ничего не открывает и не сохраняет. Он только возвращает путь к выбранному пользователем файлу. А открыть его или сохранить файл в заданном месте должна уже сама программа.
Метод setDialogTitle(String title) позволяет задать окну заголовок.
Слайд 41 Контрольные вопросы
Как в Swing создается
простое окно. Поясните классическую структуру программы с окнами.
Панель содержимого окна,
класс JPanel , менеджеры размещения : назначения и правила использования.
Как организуется ручное размещение элементов управления на панели.
Как в Swing задается размер окна. Что такое «упаковка» окна.
Дайте характеристику основных визуальных компонент библиотеки Swing
Поясните механизм обработки событий библиотеки Swing.
Дайте характеристику способов создания классов слушателей на примере слушателей событий мыши ( обработки событий от мыши). Назначение класса MouseAdapter.
Поясните общую структуру слушателей. Дайте характеристику известных вам классов слушателей.
Поясните как создаются главное и контекстное меню в Swing.
Поясните как создаются в Swing стандартные диалоговые окна.